【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());
    }
};
相关推荐
码之气三段.1 小时前
Codeforces Round 1095 (Div. 2) 补题
算法
ximu_polaris1 小时前
设计模式(C++)-行为型模式-命令模式
c++·设计模式·命令模式
wuweijianlove1 小时前
算法可扩展性建模与渐进性能分析的技术7
算法
淀粉肠kk1 小时前
【C++11】智能指针详解
开发语言·c++
不想写代码的星星1 小时前
COW(Copy-on-Write):开抄开抄,哎嘿,我装的
开发语言·c++
Sylvia-girl1 小时前
C++内存如何管理?
java·jvm·c++
shehuiyuelaiyuehao1 小时前
算法14,滑动窗口,找到字符串中所有字母异位词
算法
凯瑟琳.奥古斯特1 小时前
图论核心考点精讲
开发语言·数据结构·算法·排序算法·哈希算法
WolfGang0073212 小时前
代码随想录算法训练营 Day49 | 图论 part07
算法·图论