最直觉的解法:缓存需要移动到原数组开头的元素。
注意当循环移动n位时,相当于没有移动,所以k%n即可。
class Solution {
public:
void rotate(int nums[], int n, int k) {
int nk=k%n;
if(nk==0)
{
return;
}
vector<int> cache;
for(int i=n-nk;i<n;++i)
{
cache.push_back(nums[i]);
}
for(int i=n-nk-1;i>=0;--i)
{
nums[i+nk]=nums[i];
}
for(int i=0;i<nk;++i)
{
nums[i]=cache[i];
}
return;
}
};
上述解法利用了额外O(k)的空间,一个比较巧妙的利用O(1)空间的解法如下:
class Solution {
public:
void reverse(int* start,int* end)
{
end--;
while(start<end)
{
int tmp=*start;
*start=*end;
*end=tmp;
start++;
end--;
}
}
void rotate(int nums[], int n, int k) {
int nk=k%n;
reverse(nums,nums+n);
reverse(nums,nums+nk);
reverse(nums+nk,nums+n);
}
};
想要想到本解法,关键要有自顶向下的全局观。
本题比较正统的解法其实是cycle sorting,可以百度之,
代码如下:
class Solution
{
public:
void rotate(int nums[], int n, int k)
{
if ((n == 0) || (k <= 0))
{
return;
}
int cntRotated = 0;
int start = 0;
int curr = 0;
int numToBeRotated = nums[0];
int tmp = 0;
// Keep rotating the elements until we have rotated n
// different elements.
while (cntRotated < n)
{
do
{
tmp = nums[(curr + k)%n];
nums[(curr+k)%n] = numToBeRotated;
numToBeRotated = tmp;
curr = (curr + k)%n;
cntRotated++;
} while (curr != start);
// Stop rotating the elements when we finish one cycle,
// i.e., we return to start.
// Move to next element to start a new cycle.
start++;
curr = start;
numToBeRotated = nums[curr];
}
}
};
还有一种递归交换的方法可以解决这个问题,在编《程珠玑》第二章里有对这个问题的不同做法的详细讨论。
class Solution {
public:
void swapPart(int nums[],int start1,int end1,int start2,int end2)
{
for(int i=0;(start1+i)<end1;++i)
{
int tmp=nums[start1+i];
nums[start1+i]=nums[start2+i];
nums[start2+i]=tmp;
}
}
void recur(int nums[],int start1,int start2,int end)
{
cout<<"recur: "<<start1<<" "<<start2<<" "<<end<<endl;
if((start2-start1)==(end-start2))
{
swapPart(nums,start1,start2,start2,end);
return;
}
else if((start2-start1)>(end-start2))
{
int newStart=start1+(end-start2);
swapPart(nums,start1,newStart,start2,end);
recur(nums,newStart,start2,end);
}
else
{
int newEnd=end-(start2-start1);
swapPart(nums,start1,start2,newEnd,end);
recur(nums,start1,start2,newEnd);
}
}
void rotate(int nums[], int n, int k) {
if(n==0)
{
return ;
}
k=k%n;
if(k==0)
{
return ;
}
recur(nums,0,n-k,n);
return ;
}
};