【数组】轮转数组

题目描述

给你一个数组,将数组中的元素向右轮转 k 个位置,其中k是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

解题思路

题目要求提供多种解决方案,自己能想到的是方案1和方案2,并方案2调试很多次才能通过(不超时),方案3完全是看别人的解答分析后才提供出来的,但是方案3最巧妙耗时也最少。

方案1:

  • 初始化 int n=nums.length;
  • 提前处理k,操作:k %= n;  这个是避免重复的计算;
  • 拷贝一个数组,int[] clone = Arrays.copyOf(nums, nums.length);
  • 在循环体中,对nums进行重新赋值操作,nums[i]=clone[(i-k+n)%n];

import java.util.Arrays;

class Solution5 {
    public void rotate(int[] nums, int k) {

        int[] clone = Arrays.copyOf(nums, nums.length);

        int n = nums.length;
        k %= n;
        for (int i = 0; i < nums.length; i++) {
            nums[i] = clone[(i - k + n) % n];
        }
        System.out.println(Arrays.toString(nums));
    }

    public static void main(String[] args) {
        Solution5 solution = new Solution5();
        solution.rotate(new int[]{1, 2, 3, 4, 5, 6, 7}, 3);
    }
}

方案2:

这个方案重点就是不使用数组了,只需要部分变量就能完成整体的移动;这里通过图来分析:

【数组】轮转数组_第1张图片

  • 初始化阶段,准备index=0,value=1,k=3
  • 第一步,根据公式计算出index=(index+k)%nums.length, 找到要处理的index=3,执行nums[3]=1,value=4;
  • 第二步,根据公式计算出index=(index+k)%nums.length, 找到要处理的index=6,执行nums[6]=4,value=7;
  • 以此类推下去
  • 直到执行次数等于nums.length;其他case 考虑nums.length=6,k=3 的情况。

得到下面的代码实现:


class Solution4 {

    public void rotate(int[] nums, int k) {
        k %= nums.length;
        if (k == 0) {
            return;
        }

        int count = 0;
        for (int i = 0; i < k; i++) {

            int index = i;
            int start = index;
            int value = nums[index];

            while (true) {
                if (count >= nums.length) {
                    break;
                }

                index += k;
                if (index >= nums.length) {
                    index %= nums.length;
                }
                int temp = nums[index];
                nums[index] = value;
                value = temp;
                count++;

                if (start == index) {
                    break;
                }
            }
        }
    }

    public static void main(String[] args) {
        Solution4 solution = new Solution4();
        solution.rotate(new int[]{1, 2, 3, 4, 5, 6}, 4);
        solution.rotate(new int[]{1, 2, 3, 4, 5, 6, 7}, 3);
    }
}

方案3:

这个方案只需要3次操作,操作思路如下:

  • 准备一个reverse方法,主要是将现有数组做倒序操作;准备一个数组 int nums[] = new int[] {1,2,3,4,5,6,7}; int k = 3; 
  • 第一步,将所有数据进行reverse,nums = {7,6,5,4,3,2,1};
  • 第二步,将0到k-1的元素做reverse操作,nums = {5,6,7,4,3,2,1};
  • 第三步,将k到nums.length-1的元素做reverse操作,nums= {5,6,7,1,2,3,4};

按照这个巧妙的思路代码如下:


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);
    }

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

    public static void main(String[] args) {
        Solution solution = new Solution();
        solution.rotate(new int[]{1, 2, 3, 4, 5, 6}, 4);
        solution.rotate(new int[]{1, 2, 3, 4, 5, 6, 7}, 3);
    }
}

总结

这道题是一个要求有多种解决方案的问题,前2个方案我都能想到,但是在耗时方面都不是最好的;第三个方案,思路巧妙,代码实现简单,但我自己却没有想到。如果有更好的方案,欢迎回复。

你可能感兴趣的:(算法与数据结构,数据结构,leetcode,算法,java)