一、题目再解读
原题题干
给定一个整数数组 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]
二、新手踩坑实录(我的错误代码复盘)
错误思路描述
我一开始想通过交换 i 和 i+k 实现轮转,结果发现:
- 一轮交换后右边对了
- 左边完全乱序
- 边界超多
- 递归也很难写对
- 思路太复杂,越写越绕
三、最优解法:三次翻转法(空间 O (1),时间 O (n))
解法思路
核心思想:翻转 = 最简单的轮转
三步固定流程:
- 反转整个数组
- 反转前 k 个元素
- 反转剩下的元素
最优代码
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) 时间,效率低
结语
轮转数组这道题,三次翻转法是最简洁、最好写、面试最稳的最优解。新手不要硬刚复杂思路,掌握翻转技巧,同类题目都能快速解决。