本题有个小陷阱:k有可能大于数组长度,那我们就可以当作转了len/k圈,还剩len%k位没有转完。因此一开始就把k替换成k%len即可。
方法一:把尾部k个数保存下来,把前n-k个数向后移,再把k个数放到前面去,非常朴素的做法,空间复杂度O(k),时间复杂度O(n2)
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int len = nums.size();
k %= len;
if(k == 0) return;
if(len == 1) return;
int a[k];
for(int i = 0; i < k; ++i){
a[i] = nums[len-1-k+i+1];
}
for(int i = len-1-k; i >= 0; --i){
nums[i+k] = nums[i];
}
for(int i = 0; i < k; ++i){
nums[i] = a[i];
}
}
};
方法二:翻转数组法
nums = "----->-->"; k =3
result = "-->----->";
reverse "----->-->" we can get "<--<-----"
reverse "<--" we can get "--><-----"
reverse "<-----" we can get "-->----->"
this visualization help me figure it out :)
总体翻转,再翻转前k个值,再翻转n-k个值,相当于向右旋转了k个值。
因为这个一维数组的有趣特性,所以可以这么做,不知道二维的数组旋转是不是也可以?
class Solution {
public:
void reverse(vector<int>& a, int start, int end){
while(start < end){
swap(a[start], a[end]);
++start;
--end;
}
}
void rotate(vector<int>& nums, int k) {
int len = nums.size();
k %= len;
reverse(nums, 0, len-1);
reverse(nums, 0, k-1);
reverse(nums, k, len-1);
}
};
空间复杂度O(1),时间复杂度O(2n)即为O(n)