Rotate an array of n elements to the right by k steps.
For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7]
is rotated to [5,6,7,1,2,3,4]
.
Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
Hint:
Could you do it in-place with O(1) extra space?
Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.
新题抢先刷,这道题标为Easy,应该不是很难,我们先来看一种O(n)的空间复杂度的方法,我们复制一个和nums一样的数组,然后利用映射关系i -> (i+k)%n来交换数字。代码如下:
解法一:
class Solution { public: void rotate(vector<int>& nums, int k) { vector<int> t = nums; for (int i = 0; i < nums.size(); ++i) { nums[(i + k) % nums.size()] = t[i]; } } };
由于提示中要求我们空间复杂度为O(1),所以我们不能用辅助数组,上面的思想还是可以使用的,但是写法就复杂的多,而且需要用到很多的辅助变量,我们用题目中的例子来展示下面这种算法的nums的变化过程:
1 2 3 4 5 6 7
1 2 3 1 5 6 7
1 2 3 1 5 6 4
1 2 7 1 5 6 4
1 2 7 1 5 3 4
1 6 7 1 5 3 4
1 6 7 1 2 3 4
5 6 7 1 2 3 4
解法二:
class Solution { public: void rotate(vector<int>& nums, int k) { if (nums.empty() || (k %= nums.size()) == 0) return; int n = nums.size(), start = 0, i = 0, cur = nums[i], cnt = 0; while (cnt++ < n) { i = (i + k) % n; int t = nums[i]; nums[i] = cur; if (i == start) { ++start; ++i; cur = nums[i]; } else { cur = t; } } } };
根据热心网友waruzhi的留言,这道题其实还有种类似翻转字符的方法,思路是先把前n-k个数字翻转一下,再把后k个数字翻转一下,最后再把整个数组翻转一下:
1 2 3 4 5 6 7
4 3 2 1 5 6 7
4 3 2 1 7 6 5
5 6 7 1 2 3 4
解法三:
class Solution { public: void rotate(vector<int>& nums, int k) { if (nums.empty() || (k %= nums.size()) == 0) return; int n = nums.size(); reverse(nums.begin(), nums.begin() + n - k); reverse(nums.begin() + n - k, nums.end()); reverse(nums.begin(), nums.end()); } };
由于旋转数组的操作也可以看做从数组的末尾取k个数组放入数组的开头,所以我们用STL的push_back和erase可以很容易的实现这些操作。
解法四:
class Solution { public: void rotate(vector<int>& nums, int k) { if (nums.empty() || (k %= nums.size()) == 0) return; int n = nums.size(); for (int i = 0; i < n - k; ++i) { nums.push_back(nums[0]); nums.erase(nums.begin()); } } };
下面这种方法其实还蛮独特的,通过不停的交换某两个数字的位置来实现旋转,根据网上这个帖子的思路改写而来,数组改变过程如下:
1 2 3 4 5 6 7
5 2 3 4 1 6 7
5 6 3 4 1 2 7
5 6 7 4 1 2 3
5 6 7 1 4 2 3
5 6 7 1 2 4 3
5 6 7 1 2 3 4
解法五:
class Solution { public: void rotate(vector<int>& nums, int k) { if (nums.empty()) return; int n = nums.size(), start = 0; while (n && (k %= n)) { for (int i = 0; i < k; ++i) { swap(nums[i + start], nums[n - k + i + start]); } n -= k; start += k; } } };
参考资料:
https://discuss.leetcode.com/topic/9801/summary-of-c-solutions/2
https://discuss.leetcode.com/topic/24283/a-7-line-time-o-n-in-place-solution-no-reversing/2