---
# System prepended metadata

title: 189. Rotate Array
tags: [Leetcode, Array, Medium]

---

# 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的使用~