题目:189.旋转数组
给定一个整数数组
nums
,将数组中的元素向右轮转k
个位置,其中k
是非负数
思路一:
1.每次挪动旋转1位(用tmp将最后一位存起来,其余所有数据向后移,然后将tmp放在第一个位置)
2.右旋k位
知道了思路的步骤,我们也先不着急实现,先来分析一下它的时间复杂度~:
我们知道每次挪动旋转1位的时间复杂度是O(N)
接下来右旋k位,这里就要分最好情况和最坏情况了:
最好情况:k是N的倍数时,我们不需要挪动,时间复杂度是O(1)
最坏情况:k%N = N-1 则要执行N*(N-1)次 时间复杂度是O(N^2)
我们知道时间复杂度是取最坏情况的
综上,思路一的时间复杂度是O(N^2)
不过这个思路博主已经在力扣上跑过了,最终超出时间限制,所以对于这道题目,时间复杂度为
O(N^2) 是不行的,我们得用其他的,时间复杂度更低的思路实现~
接下来我们来看一下思路二:
1.前n-k个逆置
2.后k个逆置
3.整体逆置
同样,我们也来分析一下它的时间复杂度,看看它的性能是否值得我们去写
简单计算得出是2*N,所以它的时间复杂度是O(N)
接下来我们就来实现一下
这里我先单独写一个逆置函数,因为这个功能我们等会要用三次, 单独写一个才更加方便之后的复用~
void Reverse(int* nums, int start, int end) //写一个逆置的函数
{
while (start <end)
{
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start ++;
end --;
}
}
接下来我们写一下rotate函数,其实写完上面这个函数后就非常简单了:
代码如下:
void rotate(int* nums, int numsSize, int k)
{
k %= numsSize;//防止越界
Reverse(nums, 0, numsSize-k-1);//前n-k个逆置
Reverse(nums, numsSize-k, numsSize-1);//后k个逆置
Reverse(nums, 0, numsSize - 1);//整体逆置
}
这个思路就可以通过啦~
好,这是这个题的第二个思路
但是这个思路二的难点在于它怎么想出来,如果我们第一次做这类题,恐怕 还是难以下手,那么有没有我们初见就能想出来并且能过通过测试的思路呢?
所以接下来再看一下思路三~
思路三:
1.创建一个新的数组tmp
2.将原数组nums后面的k个拷贝到新数组tmp前面的位置
(原数组对应下标为n-k~n-1,新数组对应下标为0~k-1)
3.将原数组nums前面的n-k个拷贝到新数组tmp后面的位置
(原数组对应下标为0~n-k-1,新数组对应下标为k~n-1)
4.将拷贝完的tmp的数据放回原数组nums中
思路有了,我们也先看一下它的时间复杂度是否可行:
先拷后k个,再拷前n-k个用了n再整体拷回,
所以总共是2*n 即时间复杂度是O(N)
既然可行,
下面来写一下代码
这里的拷贝博主直接使用memcpy函数,关于memcpy的具体用法可以在Cplusplus中搜索
这里我就大概介绍一下:
从函数的定义中,我们可以看出第一个参数是目标,第二个是原,第三个参数是字节数
代码如下:
void rotate(int* nums, int numsSize, int k)
{
k %= numsSize;//防止越界
int tmp[numsSize];
int n = numsSize;;
memcpy(tmp,nums+n-k,sizeof(int)*k);
memcpy(tmp+k,nums,sizeof(int)*(n-k));
memcpy(nums,tmp,sizeof(int)*n);
}
然后就过了
好啦,今天的旋转数组问题就结束啦,如果文中分析,题解代码有不足的地方欢迎大家在评论区讨论和指正
让我们在接下来的时间里一起学习,一起进步吧~