【LC100】No189. 轮转数组

题目描述

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

提示:

  • 1 <= nums.length <= 105

  • -231 <= nums[i] <= 231 - 1

  • 0 <= k <= 105

进阶:

你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?

示例

示例 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]

示例 2:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

链接

https://leetcode.cn/problems/rotate-array/description/?envType=study-plan-v2&envId=top-100-liked

思路

简单吗?如简单。

但看上去真的很简单。

解法一:用额外数组保存结果

对于数组元素 nums[i],向右轮转 k 个位置后,其从下标 i 移动到 i + k 的位置。i + k 一旦超过数组长度,会重新从数组左端 0 的位置继续移动,我们可以通过对数组长度取余来找到这个新位置。

即,移动后的最终位置为 (i + k) % len,len为数组长度。

因此,我们使用一个额外数组,将每个元素保存到应该存放的新位置,最后复制给原数组 nums。

Q:为什么使用复制不使用直接复制

A:nums 在本题中通过方法形参传递进来,此时方法内的 nums 是原始引用的拷贝副本,只是和原始引用一样,指向同一个数组对象。

如果使用赋值,将 res 直接赋值给 nums,修改的也只是方法内 nums 这个引用指向了新的数组 res,原始引用处的指向不变。

但使用复制方法,修改对象内容,会影响到原始数组对象。

代码

class Solution {
    public void rotate(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k == 0) {
            return;
        }
        int len = nums.length;
        int[] res = new int[len];
        for (int i = 0; i < len; i++) {
            res[(i + k) % len] = nums[i];
        }
        // System.arraycopy(原数组, 原数组起始下标, 目标数组, 目标数组起始下标, 数组长度)
        System.arraycopy(res, 0, nums, 0, len);
    }
}
  • 时间复杂度:O(n)

  • 空间复杂度:O(n)

解法二:原地翻转

很数学的思路,很数学。

在示例一中,要将 [1,2,3,4,5,6,7] 翻转成 [5,6,7,1,2,3,4]。

可以看出 567 移动到了 1234 的前面,这个我们可以通过翻转整个数组实现,即变为 [7,6,5,4,3,2,1]。

继续观察,我们需要将 765 翻转成 567,同时将 4321 翻转成 1234,最后所得结果即为题目所求。

有一个需要注意的点是,由于 k 可能大于数组长度,例如数组长度为 7,k 为 10,但对于此数组来说,轮转 7 次之后的结果和原数组一样。所以为了减少翻转次数,我们可以先对 k 在数组长度上取余

k %= len

代码

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

    private void reverse(int[] nums, int i, int j) {
        while(i < j) {
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
            i++;
            j--;
        }
    }
}
  • 时间复杂度:O(n)

  • 空间复杂度:O(1)


【LC100】No189. 轮转数组
https://tiamo495.com//archives/lc100-no189.-lun-zhuan-shu-zu
作者
tiamo495
发布于
2025年07月25日
许可协议