题目链接

轮转数组

题目描述

image.png

解题思路

方法一:辅助数组

思路简单,直接上实现代码:

  1. class Solution {
  2. public void rotate(int[] nums, int k) {
  3. int len = nums.length;
  4. int[] arr = new int[len];
  5. for(int i=0; i<len; i++) {
  6. arr[i] = nums[i];
  7. }
  8. // 找到1的位置
  9. int oneIndex = k % len;
  10. int arrIndex = 0;
  11. for(int i=oneIndex; i<len; i++) {
  12. nums[i] = arr[arrIndex++];
  13. }
  14. for(int i=0; i<oneIndex; i++) {
  15. nums[i] = arr[arrIndex++];
  16. }
  17. }
  18. }

方法二:环形替换

假设替换i位置的元素,替换后的位置应该为:(i+ k)% len;这里不借用辅助数组开辟新的空间,每次替换保存替换位置的元素,然后进行下一轮元素查找替换;直到替换的位置回到原点,则继续往后进行替换,直到替换了n次;

image.png

实现代码:

  1. class Solution {
  2. public void rotate(int[] nums, int k) {
  3. int n = nums.length;
  4. k = k % n;
  5. int count = gcd(k, n);
  6. for (int start = 0; start < count; ++start) {
  7. int current = start;
  8. int prev = nums[start];
  9. do {
  10. int next = (current + k) % n;
  11. int temp = nums[next];
  12. nums[next] = prev;
  13. prev = temp;
  14. current = next;
  15. } while (start != current);
  16. }
  17. }
  18. public int gcd(int x, int y) {
  19. return y > 0 ? gcd(y, x % y) : x;
  20. }
  21. }

方法三:翻转数组

该方法基于如下的事实:当我们将数组的元素向右移动 k 次后,尾部 kmodn 个元素会移动至数组头部,其余元素向后移动 kmodn 个位置。

该方法为数组的翻转:我们可以先将所有元素翻转,这样尾部的 kmodn 个元素就被移至数组头部,然后我们再翻转 [0,kmodn−1] 区间的元素和[kmodn,n−1] 区间的元素即能得到最后的答案。

我们以 n=7,k=3 为例进行如下展示:
image.png

class Solution {
    public void rotate(int[] nums, int k) {
        k %= nums.length;
        reverse(nums, 0, nums.length - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.length - 1);
    }

    public void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start += 1;
            end -= 1;
        }
    }
}