189. 轮转数组
📚核心逻辑
本解法采用 三次翻转(数组反转)的策略:
- 整体翻转:先将整个数组进行翻转,这样原本在末尾的元素就移动到了开头。
- 局部翻转(前 k 个):将前
k个元素进行翻转,恢复这部分的正确顺序。 - 局部翻转(剩余部分):将剩下的元素进行翻转,恢复这部分的正确顺序。 这样通过三次原地翻转,即可在不使用额外空间的情况下完成数组的轮转。
🔥代码实现(含详细变量注释)
class Solution {
public void rotate(int[] nums, int k) {
// n:记录当前数组的长度
int n = nums.length;
// k:经过取模运算,得到实际需要向右轮转的真实步数(避免重复轮转)
k = k % n;
// 如果实际轮转步数为0,说明无需轮转,直接返回结束方法
if (k == 0) {
return;
}
// 步骤1:翻转整个数组 (索引 0 到 n-1)
Helper(nums, 0, n - 1);
// 步骤2:翻转前 k 个元素 (索引 0 到 k-1)
Helper(nums, 0, k - 1);
// 步骤3:翻转剩下的元素 (索引 k 到 n-1)
Helper(nums, k, n - 1);
}
/**
* 翻转数组中指定区间的元素
* @param nums 需要操作的原始数组
* @param start 要翻转区间的起始索引
* @param end 要翻转区间的结束索引
*/
public void Helper(int[] nums, int start, int end) {
// 双指针循环:只有当左边索引小于右边索引时才进行交换,直到两指针相遇
while (start < end) {
// exchange:用于交换两个元素的临时中转变量
int exchange = nums[start];
// 将右侧(end位置)的值覆盖到左侧(start位置)
nums[start] = nums[end];
// 将暂存的左侧原值赋值给右侧(end位置),完成一次交换
nums[end] = exchange;
// 交换完成后,左指针向右移动一位
start++;
// 交换完成后,右指针向左移动一位
end--;
}
}
}
- ⏱️复杂度分析
时间复杂度:O(N),其中 N 是数组的长度。每个元素最多被翻转两次,总时间复杂度为 O(N)。
空间复杂度:O(1),使用了常数个变量(n、k、exchange)进行原地交换,没有使用额外的数组空间。
🔍反思一下:
✨1. 这个题其实很简单,假设不是 n 的倍数的情况下(n 的倍数相当于没反转),不论你 k 是s多少次,都有一套公式可以直接解决,而且只需要反转三次

✨2. 还发现一个现象就是对于数组的一些操作吧,其实我们可以设置区间来进行操作,这样思路清晰,代码量会小很多,比如滑动窗口(处理连续子数组 / 子串等等)