原位旋转指不申请新数组、空间复杂度o(1)的数组旋转;不能仅用一次std::reverse,因其全局翻转而非按三段(全翻、前k、后n−k)局部翻转,无法得到正确结果。

什么是原位旋转?为什么不能直接用 std::reverse 一次搞定
原位旋转数组(比如向右旋转 k 步)的核心约束是:不申请新数组,空间复杂度必须为 O(1)。很多人第一反应是用 std::reverse,但只调用一次会出错——它翻转整个数组,而旋转需要的是三段局部翻转的组合。
例如数组 [1,2,3,4,5] 向右旋转 2 步,目标是 [4,5,1,2,3]。直接 std::reverse(arr, arr+5) 得到的是 [5,4,3,2,1],完全不对。
真正有效的方法是「三次翻转」:先翻转全部,再翻转前 k 个,再翻转后 n−k 个。这利用了翻转操作的可逆性和组合性,且每步都原地进行。
如何正确计算有效旋转步数并处理 k > n 的情况
旋转 k 步和旋转 k % n 步效果完全一样,因为转满一圈就回到原状。忽略这点会导致越界访问或逻辑错误(比如对长度为 3 的数组尝试翻转前 7 个元素)。
-
k = k % n必须做,且要在翻转前完成 - 如果
k == 0,直接返回,避免无意义操作 - 注意
k是向右旋转步数;若题目要求向左,等价于向右旋转n - k步
手写翻转函数比调用 std::reverse 更可控
虽然 std::reverse 本身是原位的,但传参容易出错(比如迭代器范围搞反、忘记加 begin()),而且面试或嵌入式环境可能禁用 STL 算法。手写一个双指针翻转函数更直观、更易调试。
示例实现:
void reverse(int* arr, int left, int right) {
while (left <p>调用顺序必须严格:</p>
-
reverse(arr, 0, n-1)// 全局翻转 -
reverse(arr, 0, k-1)// 前 k 个 -
reverse(arr, k, n-1)// 后 n-k 个
边界条件和类型安全最容易被忽略
实际写的时候,这几个点一不注意就会崩溃或结果错乱:
- 输入数组为空(
n == 0)或arr == nullptr,必须提前检查 -
int类型的k可能为负——题目若允许左旋负步数,应先归一化:k = ((k % n) + n) % n - 使用
size_t做索引时,k-1在k==0下会变成极大正数(无符号回绕),务必确保索引变量为有符号类型或加保护判断 - 旋转操作不改变元素值,但会改变相对位置——如果数组里存的是指针或对象,需确认拷贝/移动语义是否安全
最常漏掉的是对 k %= n 后为 0 的短路处理,以及无符号整数减法溢出。这两个问题在静态分析工具里常被标为 high severity 警告。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











