LeetCode 189.轮转数组

简介: LeetCode 189.轮转数组

💡题目分析

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

7368ab4e56974046a33e50a22dc357c3.png

5a4788e3e1984ecba9646ad433aa1021.pngff0298526a4d4217a73cb936686a20b9.png


💡解题思路

🚩思路1:暴力求解 — 旋转k次

假如我们要把数组 [1,2,3,4,5,6,7],向右旋转3

👇图解👇

0f17b188e7a84ebab7e5719387cadb6f.png

第1步:定义一个临时变量 tmp,用来存放数组最后的元素7

第2步:把数组前 n-1 个值往后挪

第3步:把 tmp 的值放入前面空位置中去

👆这样就完成了 1 次轮转,如果要轮转 k 次,就需要循环 k 次就完成了


🔔接口源码:

void rotate(int* nums, int numsSize, int k)
{
    k %= numsSize;//防止k大于numsSize
    int tmp = 0;
    for (int i = 0; i < k; i++)
    {
        tmp = nums[numsSize - 1];
        for (int j = numsSize - 1; j > 0; j--)
        {
            nums[j] = nums[j - 1];
        }
        nums[0] = tmp;
    }
}

此方法:
时间复杂度:O(N^2) — 最坏情况
空间复杂度:O(1)

🚨但是这种解法是过不了的,LeetCode会限制效率,这种方法效率太低了


🚩思路2:额外开数组

空间换时间 的做法

👇图解👇

da881fe8e5254a9cbb2fb99301504f00.png

第1步:新开辟一个数组

第2步:把后 k 个元素放到新数组的前面

第3步:再把前 n-k 个元素放到新数组的后面(n是数组中元素总个数 也就是题目中的参数 numsSize


🔔接口源码:

void rotate(int* nums, int numsSize, int k)
{
  if (k > numsSize)
  {
    k %= numsSize;
  }
  int* tmp = (int*)malloc(sizeof(int) * numsSize);
  memcpy(tmp, nums + numsSize - k, sizeof(int) * k);
  memcpy(tmp + k, nums, sizeof(int) * (numsSize - k));
  memcpy(nums, tmp, sizeof(int) * (numsSize));
  free(tmp);
  tmp = NULL;
}

此方法:
时间复杂度:O(N)
空间复杂度:O(N)


🚩思路3:三段逆置

🥰非常绝绝子的方法!!!

👇图解👇

50f0073c51f34e07a7b44cbd57833538.png

972e66ab52f6450a85353c11105c9b1c.png

1249a88f152b42d6ac941124d4c1dc0b.png第1步:对前 n-k 个逆置

第2步:对后 k 个逆置

第3步:整体逆置

此方法:
时间复杂度:O(N)
空间复杂度:O(1)

📍算法设计

先写一个逆置的函数来实现逆置的功能👇

void reverse(int* arr, int left, int right)
{
  while (left < right)
  {
    int tmp = arr[left];
    arr[left] = arr[right];
    arr[right] = tmp;
    left++;
    right--;
  }
}


🚨我们使用 reverse逆置函数的时候要注意:数组下标是从 0 开始的

🚨我们还需要注意一个问题:如果 k 超过了数组元素个数怎么办?


比如:数组是 [ 1 2 3 4 5 6 7] ,k = 8 的时候,此时数组元素个数为 7,而要求向右旋转 8 个位置,如果按照上面分析的情况,第一趟对前 n - k 逆置,也就是 7-8个逆置,难道对前 -1 个逆置吗?


仔细想一下最后的结果会是什么?

结果数组就是 [ 7 1 2 3 4 5 6 ]

🚨我们要记住这道题的核心叫 轮转数组,也就是当轮转的次数超过数组长度的时候,又是新的一轮了!


所以,如果 k 大于数组长度,故首先对 k 取余,然后再次旋转,这不会影响最终结果!

🔔接口源码:

void reverse(int* arr, int left, int right)
{
  while (left < right)
  {
    int tmp = arr[left];
    arr[left] = arr[right];
    arr[right] = tmp;
    left++;
    right--;
  }
}
void rotate(int* nums, int numsSize, int k) 
{
    if(k>numsSize)
    {
        k%=numsSize;
    }
   reverse(nums, 0, numsSize-k-1);
   reverse(nums, numsSize-k, numsSize-1);
   reverse(nums, 0, numsSize-1);
}

4282f594a4234597832e107732268c6c.png

目录
相关文章
|
1月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
38 0
|
3月前
|
算法
LeetCode第53题最大子数组和
LeetCode第53题"最大子数组和"的解题方法,利用动态规划思想,通过一次遍历数组,维护到当前元素为止的最大子数组和,有效避免了复杂度更高的暴力解法。
LeetCode第53题最大子数组和
LeetCode------找到所有数组中消失的数字(6)【数组】
这篇文章介绍了LeetCode上的"找到所有数组中消失的数字"问题,提供了一种解法,通过两次遍历来找出所有未在数组中出现的数字:第一次遍历将数组中的每个数字对应位置的值增加数组长度,第二次遍历找出所有未被增加的数字,即缺失的数字。
|
1月前
【LeetCode-每日一题】 删除排序数组中的重复项
【LeetCode-每日一题】 删除排序数组中的重复项
19 4
|
1月前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
18 0
Leetcode第三十三题(搜索旋转排序数组)
|
1月前
|
算法 C++
Leetcode第53题(最大子数组和)
这篇文章介绍了LeetCode第53题“最大子数组和”的动态规划解法,提供了详细的状态转移方程和C++代码实现,并讨论了其他算法如贪心、分治、改进动态规划和分块累计法。
57 0
|
1月前
|
C++
【LeetCode 12】349.两个数组的交集
【LeetCode 12】349.两个数组的交集
16 0
|
3月前
|
算法
LeetCode第81题搜索旋转排序数组 II
文章讲解了LeetCode第81题"搜索旋转排序数组 II"的解法,通过二分查找算法并加入去重逻辑来解决在旋转且含有重复元素的数组中搜索特定值的问题。
LeetCode第81题搜索旋转排序数组 II
|
3月前
|
算法 索引
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
这篇文章介绍了LeetCode第34题"在排序数组中查找元素的第一个和最后一个位置"的解题方法,通过使用双指针法从数组两端向中间同时查找目标值,有效地找到了目标值的首次和最后一次出现的索引位置。
LeetCode第34题在排序数组中查找元素的第一个和最后一个位置
|
3月前
|
算法
LeetCode第33题搜索旋转排序数组
这篇文章介绍了LeetCode第33题"搜索旋转排序数组"的解题方法,通过使用二分查找法并根据数组的有序性质调整搜索范围,实现了时间复杂度为O(log n)的高效搜索算法。
LeetCode第33题搜索旋转排序数组