#LeetCode匠#轮转数组

156 阅读1分钟

「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」。

将指定的数组按某个数量级后移,你能想到集中算法实现呢?今天给大家展示下3种不同的解法,由浅入深的理解下。

题目描述

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

题目示例

题目解法

解法一:遍历拷贝法

在遍历数组过程,借助新的数组锚定数值,而后复制

/**
 * 遍历拷贝法
 */
class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        // 用于存储轮转后的数据
        int[] newArray = new int[n];
        for (int i = 0; i < n; ++i) {
            // 锚定每个节点移动后的值
            newArray[(i + k) % n] = nums[i];
        }
        // 系统函数拷贝
        System.arraycopy(newArray, 0, nums, 0, n);
    }
}

解法二:双指针动态规划

借助双指针标符,一个是指针,一个是移动值

/**
 * 双指针动态规划
 */
class Solution {
    public void rotate(int[] nums, int k) {
        if (k < 1 || nums.length <= 1) {
            return;
        }
        // 移位变更值
        int hold = nums[0];
        // 指针变动
        int index = 0;
        int length = nums.length;
        boolean[] visited = new boolean[length];
        for (int i = 0; i < length; i++) {
            index = (index + k) % length;
            if (visited[index]) {
                index = (index + 1) % length;
                hold = nums[(index + length - k) % length];
            }
            visited[index] = true;
            int temp = nums[index];
            nums[index] = hold;
            hold = temp;
        }
    }
}

解法三:动态翻转数组

最为精妙的解法,先翻转全部,再反转前K个,后反转余下的

/**
 * 动态翻转数组
 */
class Solution {
    public void rotate(int[] nums, int k) {
        int length = nums.length;
        k = k % length;
        // 全部翻转
        reverseNum(nums, 0, length - 1);
        // 反转前k个
        reverseNum(nums, 0, k - 1);
        // 翻转后几个
        reverseNum(nums, k, length - 1);
    }

    public void reverseNum(int[] nums, int left, int right){
        while (left < right) {
            int temp = nums[left];
            nums[left++] = nums[right];
            nums[right--] = temp;
        }
    }
}

LeetCode原题链接:leetcode-cn.com/problems/ro…