std::rotate最省心但需注意迭代器方向:第三个参数是新序列起始位置而非移动位数,左移k位调用std::rotate(begin, begin+k, end),右移等价于左移n−k位,k需先对n取模;手写三次翻转法更可控,适合禁用STL场景。

用 std::rotate 最省心,但得注意迭代器方向
直接调用 std::rotate 是 C++ 标准库提供的最可靠方式,它原地完成循环移动,时间复杂度 O(n),且不依赖数组是否连续(对 vector、deque、普通数组都适用)。关键点在于:第三个参数是“新序列起始位置”,不是移动位数。
比如要把 arr = {1,2,3,4,5} 左移 2 位(变成 {3,4,5,1,2}),要写成:
std::rotate(arr.begin(), arr.begin() + 2, arr.end());
右移 2 位则等价于左移 3 位(n−k),也可换算为:
std::rotate(arr.begin(), arr.begin() + 3, arr.end());
- 别传错迭代器:第二个参数必须指向“要移到开头的首个元素”,不是偏移量本身
- 对原始数组需转成指针区间:
std::rotate(arr, arr + k, arr + n) - 若 k 可能大于 n,先做
k %= n,否则行为未定义
手写翻转法更可控,适合面试或嵌入式环境
当不能用 STL(比如裸机开发、禁用算法库),或想明确控制每一步时,“三次翻转”是经典解法:先翻转整个数组,再翻转前 k 个,再翻转后 n−k 个。逻辑清晰、无额外空间、边界容易验证。
立即学习“C++免费学习笔记(深入)”;
左移 k 位的实现示例(k 已对 n 取模):
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
void rotate_left(int* arr, int n, int k) {
if (n <= 1 || k == 0) return;
std::reverse(arr, arr + n);
std::reverse(arr, arr + n - k);
std::reverse(arr + n - k, arr + n);
}- 右移只需把第二步和第三步顺序调换,或统一转成左移:右移 k 等价于左移
n - k - 注意
std::reverse的区间是左闭右开,别写成arr + n - k + 1 - 手写
reverse也很简单,两个指针向中间交换即可,避免依赖 STL
用取模索引访问适合只读场景,但别真用来改原数组
如果只是需要“逻辑上循环访问”,比如遍历、打印、计算,完全没必要移动内存——直接用 (i + k) % n 算下标即可。这在环形缓冲区、FFT 索引重排中很常见。
例如遍历左移 k 位后的数组:
for (int i = 0; i < n; ++i) {
int actual_idx = (i + k) % n;
std::cout << arr[actual_idx] << " ";
}- 这种写法零开销,但仅适用于只读或构造新数组;若要修改原数组顺序,仍得用
rotate或翻转 -
%对负数行为依赖编译器:C++20 前推荐用((i + k) % n + n) % n避免负余数 - 现代 CPU 对
%优化不错,但频繁取模仍比指针加法慢,高频循环里可预计算偏移数组
vector 和原始数组传参差异容易导致崩溃
传 std::vector 给旋转函数时,别直接传 v.data() 后当成裸指针操作——除非你确保 size 不变且没发生 realloc。更安全的是统一用迭代器接口,或封装成模板函数。
错误示范:
std::vector<int> v = {1,2,3,4,5};
rotate_left(v.data(), v.size(), 2); // 危险:v 可能在别处被 move 或 resize- 推荐写成模板函数:
template<typename it> void rotate_left(It first, It last, int k)</typename> - 对 vector 调用:
rotate_left(v.begin(), v.end(), k),自动适配 - 原始数组调用:
rotate_left(arr, arr + n, k),类型推导为int*,也成立
真正麻烦的不是算法本身,而是混用裸指针和容器时忘了生命周期管理——移动后原 vector 还在,但 data 指针可能已失效。

















