【Hot 100 刷题计划】 LeetCode 189. 轮转数组 | C++ 三次反转经典魔法 (O(1) 空间)

LeetCode 189. 轮转数组

📌 题目描述

题目级别:中等

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

进阶要求:

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

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

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

💡 破题思路:三次反转 (数组魔术)

最容易想到的办法是开辟一个新数组,把后面的元素搬到前面,前面的搬到后面。但这会消耗 O(N) 的额外空间。

要想实现 O(1) 空间复杂度的"原地"轮转,最经典的解法就是**"三次反转法"**。

这就像是一个精妙的数学魔术。以 nums = [1,2,3,4,5,6,7], k = 3 为例,我们需要把最后 3 个元素搬到最前面。

按照本解法的独家顺序:

  1. 反转前半段 :把前 n-k 个元素反转。[1,2,3,4] 变成了 [4,3,2,1]
    此时数组:[4,3,2,1, 5,6,7]
  2. 反转后半段 :把最后 k 个元素反转。[5,6,7] 变成了 [7,6,5]
    此时数组:[4,3,2,1, 7,6,5]
  3. 整体反转 :把整个数组头尾对调!前面的去了后面,后面的来了前面,而且之前内部被打乱的顺序,在这一次整体反转中负负得正,完美还原
    最终数组:[5,6,7, 1,2,3,4]

⚠️ 极客避坑点

如果 k 的值比数组长度 n 还要大,比如数组长度为 7,让你轮转 10 次,其实就等价于轮转了 10 % 7 = 3 次。所以第一步必须进行取模运算 k = k % n


💻 C++ 代码实现

cpp 复制代码
class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        
        // 核心细节:剥除多余的整圈轮转
        k = k % n;
        
        // 第一步:反转前半部分 (前 n-k 个元素)
        reverse(nums.begin(), nums.end() - k);
        
        // 第二步:反转后半部分 (后 k 个元素)
        reverse(nums.end() - k, nums.end());
        
        // 第三步:整体反转,首尾对调完成最终轮转
        reverse(nums.begin(), nums.end());
    }
};
相关推荐
2301_7779983436 分钟前
Linux线程同步与互斥(三):信号量与环形队列实现生产者消费者模型
linux·c语言·c++
啦啦啦啦啦zzzz36 分钟前
设计模式:单例模式和工厂模式
c++·单例模式·设计模式·工厂模式
Henry Zhu12340 分钟前
C++ 动态多态详解
c++
此生决int1 小时前
深入理解C++系列(06)——模版初阶与STL
开发语言·c++
c238561 小时前
《枚举算法 “翻译官”:用 enum class 给 “游游的礼盒” 算分》
c语言·c++·算法
noipp1 小时前
推荐题目:洛谷 P5843 [SCOI2012] Blinker 的噩梦
c语言·数据结构·c++·算法·游戏·洛谷·luogu
极客BIM工作室1 小时前
OpenCascade 倒角(Chamfer)算法完整逻辑解析
算法
冻柠檬飞冰走茶2 小时前
PTA基础编程题目集 7-20 打印九九口诀表(C语言实现)
c语言·开发语言·数据结构·算法
鱼子星_2 小时前
《算 · 法》题目解析篇(1):最近公共祖先问题,线段树,最长回文子序列
c++·算法·动态规划·递归
雾喔2 小时前
算法练习5
算法·代理模式