# 189. Rotate Array
###### tags: `Leetcode` `Medium` `Array`
Link: https://leetcode.com/problems/rotate-array/
## 思路
### 思路一 暴力解法
新开一个array,存要换到前面的数字,然后把要换到后面的数字移到后面,再把存到新array里面的数字放到前面
### 思路二 翻转Array (Very Tricky)
比较翻转过的array和答案,就会发现答案=翻转过的array,再把前k个数和后面的数各自翻转过的结果
### 思路三 (很绕 多写几遍)
我们从位置 00 开始,最初令 temp=nums[0]。根据规则,位置 00 的元素会放至 (0+k)mod n 的位置,令 x=(0+k)mod n,此时交换 temp 和 nums[x],完成位置 x 的更新。然后,我们考察位置 x,并交换 temp 和 nums[(x+k)mod n],从而完成下一个位置的更新。不断进行上述过程,直至回到初始位置 0。
容易发现,当回到初始位置 0 时,有些数字可能还没有遍历到,此时我们应该从下一个数字开始重复的过程,可是这个时候怎么才算遍历结束呢?我们不妨先考虑这样一个问题:从 0 开始不断遍历,最终回到起点 0 的过程中,我们遍历了多少个元素?
count的由来:因为从 0 开始不断遍历,最终又回到起点 0,这个过程走了a圈(a正为整数),每圈的长度为n。 这个过程中,走的每一步的长度为k,共走过了b个元素,所以走的总步长为bk,也即这a圈的长度,即a*n=b*k。 即 a*n 一定为 n,k 的公倍数。又因为我们在第一次回到起点时就要结束,因此a要最小,故a*n就是n,k的最小公倍数lcm(n,k) , 因此 b 就为lcm(n,k)/k,这说明从起点再次回到起点的过程中会访问到 lcm(n,k)/k 个元素。 为了访问到所有的元素,我们需要进行遍历的次数为,n/lcm(n,k)/k = n*k/lcm(n,k) = gcd(n,k)(最大公约数和最小公倍数的关系) 即需要遍历的次数为n和k的最大公约数。
或者也可以用单独的变量count跟踪当前已经访问的元素数量,当count = n时,结束遍历过程。
## Code
### 思路一
```java=
class Solution {
public void rotate(int[] nums, int k) {
k = k%nums.length;
int[] new_nums = new int[k];
int pos = 0;
for(int i = nums.length-k;i < nums.length;i++){
new_nums[pos] = nums[i];
pos++;
}
for(int i = nums.length-k-1;i >= 0;i--){
nums[i+k] = nums[i];
}
for(int i = 0;i < k;i++){
nums[i] = new_nums[i];
}
return;
}
}
```
### 思路二
```java=
class Solution {
public void rotate(int[] nums, int k) {
k = k%nums.length;
reverseArray(0,nums.length-1,nums);
reverseArray(0,k-1, nums);
reverseArray(k, nums.length-1, nums);
return;
}
public static void reverseArray(int start, int end, int[] nums){
int temp;
while(start<end){
temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
}
```
### 思路三
```java=
class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
k = k % n;
int count = gcd(k, n);
for (int start = 0; start < count; ++start) {
int current = start;
int prev = nums[start];
do {
int next = (current + k) % n;
int temp = nums[next];
nums[next] = prev;
prev = temp;
current = next;
} while (start != current);
}
}
public int gcd(int x, int y) {
return y > 0 ? gcd(y, x % y) : x;
}
}
```
没有计算遍历次数,只是数遍历了几个元素,遍历元素个数=nums.length时,就break的版本
```java=
class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
k = k % n;
int count = 0;
for(int i = 0;i < n;i++){
int current = i;
int prev = nums[i];
do {
int next = (current + k) % n;
int temp = nums[next];
nums[next] = prev;
prev = temp;
current = next;
count++;
} while(current != i);
if(count == n){
break;
}
}
return;
}
}
```
## Result
### 思路一
Your runtime beats **35.30 %** of java submissions.
Your memory usage beats **15.36 %** of java submissions.
### 思路二
Your runtime beats **100.00 %** of java submissions.
Your memory usage beats **90.49 %** of java submissions.
### 思路三
Your runtime beats **35.30 %** of java submissions.
Your memory usage beats **49.92 %** of java submissions.
## 注意
注意do while的使用~