题目:给定一个整数数组 nums
,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。(题目链接:189. 轮转数组 - 力扣(LeetCode))
首先在完成这个题目之前,我们先来捋捋自己的思路,来看看哪些是最优算法,时间复杂度小,值得我们实现。
思路一:依次挪动,挪动 k 次
假设 nums = [ 1,2,3,4,5,6,7 ],k = 3
利用变量存储最后一个数字
右旋 1 次, [ 7,1,2,3,4,5,6 ]
右旋 2 次, [ 6,7,1,2,3,4,5 ]
右旋 3 次, [ 5,6,7,1,2,3,4 ]
合计右旋3次
时间复杂度:O(N^2)
空间复杂度:O(1)
思路二:用空间换时间,开额外数组(将k个元素挪动到新数组中),再将原数组剩余的拷贝到新数组中。
时间复杂度:O(N)
空间复杂度:O(N)
代码实现:
void rotate(int* nums, int numsSize, int k){
int n= numsSize;
k %= n;
int* tmp=(int *)malloc(sizeof(int) * n);
memcpy(tmp,nums+n-k,sizeof(int) * k);
memcpy(tmp+k , nums , sizeof(int) * (n-k));
memcpy(nums , tmp , sizeof(int) * (n));
free(tmp);
}
思路三:旋转三次
4 3 2 1 5 6 7 前 n - k 个逆置
4 3 2 1 7 6 5 后 k 个逆置
5 6 7 1 2 3 4 整体逆置
时间复杂度:O(N)
空间复杂度:O(1)
void reserve(int *a,int left,int right)
{
while(left<right)
{
int tmp=a[left];
a[left]=a[right];
a[right] = tmp;
++left;
--right;
}
}
void rotate(int* nums, int numsSize, int k){
k %= numsSize;
reserve (nums , 0 , numsSize-k-1);
reserve(nums , numsSize-k , numsSize-1);
reserve(nums, 0 , numsSize-1);
}