189. Rotate Array [Leetcode]
来源:互联网 发布:王家卫我爱你知乎 编辑:程序博客网 时间:2024/06/06 12:26
题目:
--------------------------------------------------------------------------------------------------------------------------------------
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.
[show hint]
Could you do it in-place with O(1) extra space?
如果空间复杂度没有限制的话,会简单很多,用vector即可完成。
若是空间复杂度限制在O(1)的话,想了很久都没想出一个便捷的方法。
方法一:Reverse法
看讨论区发现一个及其简单的方法:
利用reverse来解决。
如:1234567, k = 2
先将整个数列reverse成 7654321
再reverse前k个及最后n-k个数。变成6712345
哎,一口老血喷出.......
方法二:迭代替换法
用一个变量t来记下被替换掉的数字。一共替换n步。
如下, 数组 [1,2,3,4,5,6,7] k = 3
1,2,3,1,5,6,7 t = 4
1,2,3,1,5,6,4 t = 7
1,2,7,1,5,6,4 t = 3
1,2,7,1,5,3,4 t = 6
1,6,7,1,5,3,4 t = 2
1,6,7,1,2,3,4 t = 5
5,6,7,1,2,3,4 t = 1
一共7步。
注意:
当size与k互质的时候,迭代只有一个循环:比如对于1,2,3,4,5,6 k = 3,循环为:1,4,7,3,6,2,5。
当size 与 k 非互质时,有可能会发生多个循环:比如对于1,2,3,4,5,6 k = 2, size = 6 时,会在1,3,5,之间循环,以及2,4,6之间循环。可以通过判断数组下表是否跟起始下标相同以跳出循环。
(证明在下一个方法里讲)
代码如下:
class Solution {public: void rotate(vector<int>& nums, int k) { if (k == 0 || nums.size() < 2 || k % nums.size() == 0) return; int n = nums.size(), count = 0; int pre = nums[0], i = 0, start = 0; while (count++ < n) { if (i == start) { i++; start = i; pre = nums[i]; } i = (i + k) % n; int tmp = nums[i]; nums[i] = pre; pre = tmp; } return; }};
方法三:(不知如何命名)
当k与n非互质的时候,存在大于一个的迭代循环。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
证明:
假设经过i次迭代后,回到了原点,则:
i * k = j * n(i,j为>0的整数)
当k与n互质的时候,i = n,j = k,我们知道迭代步数为n时,我们就完成了迭代过程。因此只有一个循环。
设 g = gcd(k, n); k' = k / g ; n' = n / g
i * k' = j * n'
i = n'
每次循环,迭代的步数为 n / gcd(n, k);
循环个数为 gcd (n, k);
实例:
[1,2,3,4,5,6] k = 2 的。循环个数为gcd = 2.,每个循环迭代步数为 i = 6 / 2 = 3 。
[1,2,3,4,5,6,7] k = 3, 循环个数 gcd(3,7) = 1, 每个循环迭代步数: i = 7 / 1 = 7 。
与我们的推理相合。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
我们可以通过计算有几个的循环,以及每个循环需要迭代的步数来解这道题。
这里看了leetcode讨论区的代码,由于知道每次迭代的步数,可以直接用swap来代替迭代的过程。
class Solution {public: void rotate(vector<int>& nums, int k) { if (k == 0 || nums.size() < 2 || k % nums.size() == 0) return; k = k % nums.size(); int g = gcd (nums.size(), k), count = nums.size() / g; for (int i = 0; i < g; i++) { for (int j = 1; j < count; j++) { swap(nums[i], nums[(i + j * k) % nums.size()]); } } return; } int gcd(int a, int b) { return b == 0 ? a : gcd (b, a % b); }};
https://discuss.leetcode.com/topic/11349/my-three-way-to-solve-this-problem-the-first-way-is-interesting-java/8
方法四: 交换法
通过不停地将后K个数交换到正确的位置。用start来记录为无序数组(也就是位置还不正确的数)的开始。n代表当前无序数组的个数。k表示当前无需数组需要旋转的步数。
如:
[1,2,3,4,5,6,7] k = 3
第一次交换: 5,6,7,4,1,2,3 n = 7, k = 3, start = 0
第二次交换: 5,6,7,1,2,3,4 n = 4, k = 3, start = k
[1,2,3,4,5,6,7] k = 4
4,5,6,7,2,3,1 n = 7, k = 4,start = 0
4,5,6,7,1,2,3 n = 3, k = 1, star = 4
参考了https://discuss.leetcode.com/topic/9406/3-lines-of-c-in-one-pass-using-swap/14
代码如下:
class Solution {public: void rotate(vector<int>& nums, int k) { if (nums.size() < 2) return; int n = nums.size(); for (int start = 0; k %= n; n -= k, start += k) { for (int i =0; i < k; i++) { swap(nums[start + i], nums[nums.size() - k + i]); } } return; }};
- [LeetCode]189.Rotate Array
- [Leetcode] 189.Rotate Array
- LeetCode 189. Rotate Array
- 【LeetCode】189.Rotate Array
- [leetcode] 189.Rotate Array
- 【leetcode】189. Rotate Array
- Leetcode 189. Rotate Array
- 189. Rotate Array LeetCode
- [LeetCode]189. Rotate Array
- leetcode-189.-Rotate Array
- LeetCode 189. Rotate Array
- leetcode 189. Rotate Array
- LeetCode *** 189. Rotate Array
- [LeetCode]189. Rotate Array
- LeetCode 189. Rotate Array
- leetcode-189. Rotate Array
- Leetcode 189. Rotate Array
- leetcode 189. Rotate Array
- 代码code
- 3210: 花神的浇花集会
- Vue单页应用开发流程 (Laravel + Vue + Laravel-mix)
- C#复选框
- python多进程与多线程比较
- 189. Rotate Array [Leetcode]
- HDU
- 设计模式(一)单例模式回忆篇(未完待续。。。)
- mybatis 5.0 报错 Cannot convert value of type ‘com.github.pagehelper.PageHelper’ to required type ‘org
- android 读取asset下的文件注意事项
- mybatis入门,大牛们教你快速搭建!!!
- PAT--1051. 复数乘法 (15)
- 搞懂树状数组
- 微信小程序开发1