【LeetCode热题100道笔记】轮转数组

题目描述

给定一个整数数组 nums,将数组中的元素向右轮转 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

示例 2:

输入:nums = -1,-100,3,99, k = 2

输出:3,99,-1,-100

解释:

向右轮转 1 步: 99,-1,-100,3

向右轮转 2 步: 3,99,-1,-100

提示:

1 <= nums.length <= 105

-231 <= numsi <= 231 - 1

0 <= k <= 105

进阶:

尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。

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

思考一:使用额外数组

直接计算每个元素旋转后的新位置,借助额外数组存储结果后再复制回原数组。

算法过程

  1. 计算有效旋转步数 k = k % n(n为数组长度)
  2. 创建与原数组等长的新数组
  3. 遍历原数组,将每个元素 nums[i] 放入新数组的 (i + k) % n 位置
  4. 将新数组元素复制回原数组

复杂度:时间O(n),空间O(n)(额外数组占用)

代码

javascript 复制代码
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
    const n = nums.length;
    k = k % n;
    if (k === 0) return;
    
    const temp = [...nums]; // 创建原数组副本
    for (let i = 0; i < n; i++) {
        // 计算旋转后位置:原索引i的元素移到(i + k) % n
        nums[(i + k) % n] = temp[i];
    }
};

思考二:环形替换

核心思路:从起始位置开始,将元素依次移动到旋转后的目标位置,形成闭环后切换到下一个未处理的位置,直到所有元素都被移动。

算法过程

  1. 计算有效旋转步数 k = k % n,若k为0则返回
  2. 初始化计数器 count = 0(记录已处理元素数量)
  3. 从索引0开始循环:
    • 记录当前位置 current 和该位置的元素 prev
    • 计算目标位置 next = (current + k) % n
    • 交换 prev 与目标位置元素,更新 currentnext
    • 重复上述步骤,直到回到起始位置(形成闭环)
    • 计数器加1,若未处理完所有元素则从下一个索引继续

代码

javascript 复制代码
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
    const n = nums.length;
    k = k % n;
    if (k === 0) return;
    
    let count = 0; // 已处理的元素数量
    for (let start = 0; count < n; start++) {
        let current = start;
        let prev = nums[start];
        do {
            const next = (current + k) % n;
            [prev, nums[next]] = [nums[next], prev]; // 交换元素
            current = next;
            count++;
        } while (current !== start); // 回到起点时结束当前环
    }
};

思考三:反转数组

将数组向右旋转k步,可通过三次反转操作实现原地修改:先反转整个数组,再分别反转前k个元素和剩余元素,以此等价于直接旋转的效果,避免使用额外空间。

算法过程

  1. 计算有效旋转步数:k = k % 数组长度(处理k大于数组长度的情况),若k为0则无需旋转
  2. 第一次反转:将整个数组从索引0到末尾反转
  3. 第二次反转:将数组前k个元素(索引0到k-1)反转
  4. 第三次反转:将数组剩余元素(索引k到末尾)反转

通过三次局部反转,最终实现数组整体向右旋转k步的效果,时间复杂度O(n),空间复杂度O(1)。

代码

javascript 复制代码
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
    const len = nums.length;
    const count = k % len;
    if (count === 0) return;
    reverse(nums, 0, len-1);
    reverse(nums, 0, count-1);
    reverse(nums, count, len-1);
};

function reverse(nums, begin, end) {
    while (begin < end) {
        [nums[begin], nums[end]] = [nums[end], nums[begin]];
        begin++;
        end--;
    }
}
相关推荐
兰令水39 分钟前
leecodecode【面试150】【2026.6.14打卡-java版本】
java·算法·面试
小满Autumn4 小时前
log4net 日志框架 — 从配置到实战速查手册
笔记·c#·.net·wpf·上位机·log4net
noipp7 小时前
推荐题目:洛谷 P10907 [蓝桥杯 2024 国 B] 蚂蚁开会
c语言·c++·算法·编程·洛谷
程序员二叉8 小时前
【JUC】线程池全套深度详解|参数|流程|拒绝策略|调优|异常处理
java·开发语言·jvm·算法·面试·juc
青山木8 小时前
Hot 100 --- 轮转数组
java·数据结构·算法
徐小夕9 小时前
Loop Engineering 深度解析与实战指南(全网最全)
前端·算法·github
北域码匠10 小时前
SHA-1算法:安全哈希原理与应用解析
算法·c#·哈希算法
袁小皮皮不皮10 小时前
1.HCIP BFD 学习笔记(优化版)
服务器·网络·笔记·网络协议·学习·智能路由器·ip
手写码匠11 小时前
手写 GraphRAG:从零实现图增强检索增强生成系统
人工智能·深度学习·算法·aigc
BomanGe111 小时前
NSK重载高刚性滚珠丝杠技术详解
经验分享·算法·规格说明书