LeetCode 189.轮转数组:三次Revese秒杀法

4 阅读2分钟

一、题目再解读

原题题干

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。必须原地修改数组,O (1) 额外空间 复杂度。

核心规则(抓重点)

  • 原地修改:不能新建数组,只能在原数组操作,空间复杂度 O(1)
  • 向右轮转 k 位:最后 k 个元素移动到数组最前面
  • 无需返回数组,只需要修改原数组
  • k 可能大于数组长度,需要先取模 k = k % len

示例演示

输入:nums = [1,2,3,4,5,6,7], k = 3输出:[5,6,7,1,2,3,4]


二、新手踩坑实录(我的错误代码复盘)

错误思路描述

我一开始想通过交换 ii+k 实现轮转,结果发现:

  • 一轮交换后右边对了
  • 左边完全乱序
  • 边界超多
  • 递归也很难写对
  • 思路太复杂,越写越绕

三、最优解法:三次翻转法(空间 O (1),时间 O (n))

解法思路

核心思想:翻转 = 最简单的轮转

三步固定流程:

  1. 反转整个数组
  2. 反转前 k 个元素
  3. 反转剩下的元素

最优代码

plaintext


var rotate = function(nums, k) {
    //裁枝
    let len=nums.length;
    if((len===0)||(len===1)){
        return  nums;
    }
    //把k化成合法的形式
    k=k%len;
    
    swap=function(nums,x,y){
        let temp=nums[x];
        nums[x]=nums[y];
        nums[y]=temp;
    }
    reverse=function(nums,left,right){
        while(left<right){
            swap(nums,left,right);
            left++;
            right--;
        }
    }
    //1.全部翻转一次
    reverse(nums,0,len-1);
 
    //2.前面K个翻转
     reverse(nums,0,k-1);
     
    //3.后面的翻转
     reverse(nums,k,len-1);
     
     return nums;
};

代码解释

  • 先对 k 取模,避免 k 大于数组长度
  • 写一个通用翻转函数:左右指针向中间夹逼交换
  • 三次翻转 = 完美轮转

四、复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1) 原地

五、举一反三:其他解法(可选)

方法 1:环状替换(难,不推荐新手)

思路:把元素放到最终位置,处理循环分组缺点:极难理解,边界多

方法 2:暴力移动(简单但超时)

思路:每次移动一位,移动 k 次缺点:O (nk) 时间,效率低


结语

轮转数组这道题,三次翻转法是最简洁、最好写、面试最稳的最优解。新手不要硬刚复杂思路,掌握翻转技巧,同类题目都能快速解决。