(15)LeetCode 189. 轮转数组

LeetCode 189. 轮转数组(三次反转法)

题目描述

给定一个整数数组 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]

解法思路:三次反转法

核心思想

向右轮转 k 位,本质上是将数组的后 k 个元素移动到数组前面,同时保持顺序不变。

我们可以通过三次数组反转来实现原地操作,无需额外空间。

算法步骤

  1. 取模 :k = k % n,因为轮转 n 次后数组恢复原样,只需处理有效偏移。
  2. 反转整个数组 :将 nums 完全反转。
  3. 反转前 k 个元素 :将前 k 个元素反转,它们原本是原数组的后 k 个(倒序),反转后恢复正确顺序,并移到开头。
  4. 反转后 n-k 个元素:将剩余元素反转,恢复其原本顺序,放在开头之后。

数学推导

设原数组为 [a₁, a₂, ..., aₙ],向右轮转 k 位后目标为 [aₙ₋ₖ₊₁, ..., aₙ, a₁, ..., aₙ₋ₖ]。

  • 第一次反转:[a₁, ..., aₙ] → [aₙ, aₙ₋₁, ..., a₁]
  • 第二次反转(前 k 个):前 k 个为 [aₙ, aₙ₋₁, ..., aₙ₋ₖ₊₁] → 反转得 [aₙ₋ₖ₊₁, ..., aₙ](即为目标的前半部分)
  • 第三次反转(后 n-k 个):后 n-k 个为 [aₙ₋ₖ, ..., a₁] → 反转得 [a₁, ..., aₙ₋ₖ](即为目标的后半部分)

最终得到正确结果。


代码实现(C++)

cpp 复制代码
class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k %= n;                      // 处理无效轮转
        reverse(nums.begin(), nums.end());       // 反转整个数组
        reverse(nums.begin(), nums.begin() + k); // 反转前 k 个
        reverse(nums.begin() + k, nums.end());   // 反转后 n-k 个
    }
};

代码说明

  • reverse 是 C++ STL 中的双向迭代器反转函数,时间复杂度 O(n)。
  • 边界情况:k = 0 或 k 为 n 的倍数时,k 取模后为 0,此时 begin() + 0 与 begin() 相同,第三次反转整个数组(相当于反转两次),数组不变,符合预期。

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组长度。三次反转总共遍历数组常数次。
  • 空间复杂度:O(1),只使用了常数个额外变量,原地修改。

举例演示

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

步骤 操作 数组状态
初始 - [1, 2, 3, 4, 5, 6, 7]
① 反转整个数组 [7, 6, 5, 4, 3, 2, 1]
② 反转前 3 个元素(索引 0~2) [5, 6, 7, 4, 3, 2, 1]
③ 反转后 4 个元素(索引 3~6) [5, 6, 7, 1, 2, 3, 4]

最终结果 [5, 6, 7, 1, 2, 3, 4] 正确。


边界情况测试

  • k = 0:数组不变。
  • k = n:取模后为 0,数组不变。
  • k > n :如 k = 10, n = 7,取模后 k = 3,等价于轮转 3 位,正确。
  • 空数组 :n = 0 时需特殊处理,但题目一般不会给空数组,若处理可提前判断。

总结

  • 三次反转法是一种巧妙的原地算法,利用反转的逆序特性实现区间交换。
  • 注意取模操作避免冗余轮转,并确保反转区间合法。
相关推荐
weixin_307779132 小时前
C++代码实现MATLAB中的dlarray函数功能
开发语言·c++·算法·matlab
hetao17338378 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
Zootopia6268 小时前
飞行力学知识梳理1|飞行性能与稳定性
人工智能·python·算法·机器学习·无人机·学习方法·信息与通信
longlongzihan8 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
2601_960356389 小时前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
h_a_o777oah10 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO910 小时前
指针的算术运算详解
java·数据结构·算法
Coder-magician10 小时前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论
垆边人似月.10 小时前
VLAN 资源池(100~200 分档)
数据结构·算法
潼心1412o11 小时前
C++初阶(长期更新)第6讲:类和对象(下)
开发语言·c++·算法