不能用额外空间反转数组,是指除索引变量和临时交换变量外,禁止创建新数组或容器;双指针原地交换是符合O(1)空间要求的标准解法,left从0开始、right从size-1开始,循环条件为left<right,逐对交换后向中间靠拢。

为什么不能用额外空间反转数组
所谓“不使用额外空间”,是指除了几个用于索引和临时交换的变量外,不能申请新数组、不能用 std::vector 或 std::stack 等容器辅助。常见错误是写成新建数组再倒序赋值,这用了 O(n) 额外空间;或者调用 std::reverse 却没意识到它内部仍是原地操作——其实它是合规的,但很多人误以为它“开销大”而自己重写反而出错。
用双指针原地交换是最直接解法
核心思路:首尾指针向中间靠拢,每次交换对应元素,直到两指针相遇。这是标准且最易理解的 O(1) 空间、O(n) 时间解法。
- 起始时
left = 0,right = size - 1 - 循环条件必须是
left (不是 <code>left ),否则中间元素会被交换两次,等于没变 - 交换用
std::swap(arr[left], arr[right])最安全;手写临时变量也行,但别漏掉int temp = arr[left]这类基础步骤 - 对
std::array、原始数组、std::vector都适用,只要能随机访问
void reverseArray(int arr[], int n) {
int left = 0, right = n - 1;
while (left < right) {
std::swap(arr[left], arr[right]);
left++;
right--;
}
}使用 std::reverse 是合法且推荐的
很多人担心 std::reverse 不满足“不使用额外空间”要求,其实它明确是原地算法,标准规定其复杂度为 O(n) 时间、O(1) 空间。它比手写更可靠,尤其处理迭代器边界时不易出错。
- 对原始数组:需传入指针范围,如
std::reverse(arr, arr + n) - 对
std::vector:用vec.begin()和vec.end() - 对
std::string同样适用,s.reverse()是成员函数,但std::reverse(s.begin(), s.end())更统一 - 注意:传入迭代器必须有效,
arr + n不能越界,否则触发未定义行为
容易被忽略的边界情况
空数组、单元素数组、奇数长度数组的中间位置,这些场景下逻辑是否仍成立,往往被跳过测试。
立即学习“C++免费学习笔记(深入)”;
- 当
n == 0或n == 1时,left 判断直接不进循环,无需特判 - 奇数长度(如 5)时,中间索引
2不会被访问到——因为left和right在2处不会相等,而是交叉后退出,这是正确行为 - 如果用
size_t当索引类型,right初始化为n - 1可能导致right溢出为极大正数(当n == 0),务必改用有符号整型或加保护判断
真正麻烦的是指针算术和类型混用,比如对 char* 数组调用 std::reverse 时忘了加长度,或者把 sizeof(arr) 当成元素个数——这种错误不报编译错,但运行时就翻车。


















