跳转到主内容
极星编程网:以代码为星,赴技术山海!

c++中如何实现字符串的按单词反转_c++双指针法反转逻辑【详解】

必须用双指针而非std::reverse直接反转,因为后者会使单词内部字母翻转;双指针法通过整体反转、单词内反转、清理多余空格三步实现单词顺序反转且单词内字符不变,空间复杂度O(1)。 为什么要用双指针而不是
std::reverse
直接对整个字符串调用
std::reverse
会把单词内部字母也翻转,比如
"hello world"
变成
"dlrow olleh"
,而题目要的是单词顺序反转、单词内字符不变——即变成
"world hello"
。所以必须先按空格切分逻辑,再逐段反转,双指针法正好在原地完成这个过程,不依赖额外容器(如
std::vector
),空间复杂度控制在
O(1)
(不计输入字符串本身)。 双指针法三步走:整体反转 + 单词内反转 + 清理多余空格 标准做法是三个阶段,缺一不可,否则结果错乱: 第一遍:用两个指针从首尾向中间,
std::swap
整个字符串 —— 让单词顺序倒过来,但每个单词也反了 第二遍:扫描字符串,对每个连续非空格子串(即一个单词),用局部双指针把它再翻回来 第三遍:处理开头、结尾和中间多个空格的问题;若要求“单词间仅一个空格”,需额外原地压缩(否则输出含冗余空格) 注意:C++ 中
std::string
支持随机访问和修改,所以所有操作可原地进行;但若传入的是
const std::string&
,需先拷贝一份可变副本。
std::string
原地反转单词顺序的完整实现 以下代码实现「单词顺序反转 + 单词内字符不变 + 单词间仅保留一个空格」,不含额外库依赖(除
和
): 立即学习 “ C++免费学习笔记(深入) ”; AI Word 一款强大的 AI 智能内容创作平台,致力于帮助用户高效生成高质量、原创且符合 SEO 规范的各类文章。 下载
void reverseWords(std::string& s) { // 步骤1:整体反转 std::reverse(s.begin(), s.end());
// 步骤2:逐个单词反转(跳过空格,定位每个单词区间)
int n = s.length();
int i = 0;
while (i < n) {
    if (s[i] != ' ') {
        int j = i;
        while (j < n && s[j] != ' ') j++;
        std::reverse(s.begin() + i, s.begin() + j);
        i = j;
    } else {
        i++;
    }
}

// 步骤3:原地去重空格(保留单词间单空格,删首尾)
int write = 0;
for (int read = 0; read < n; ++read) {
    if (s[read] != ' ') {
        if (write != 0) s[write++] = ' '; // 单词间加空格(首个单词前不加)
        while (read < n && s[read] != ' ') {
            s[write++] = s[read++];
        }
    }
}
s.resize(write);
} 关键细节:
std::reverse
是双向迭代器安全的,适用于
std::string::iterator
;第三步中
write
指针控制实际写入位置,避免新建字符串;
s.resize(write)
截断末尾冗余字符。 容易被忽略的边界情况 很多实现在线 OJ 上失败,不是逻辑错,而是漏了这些: 输入为空字符串
""
或全空格(如
"   "
)—— 第三步压缩后应为
""
,不能 crash 单词间有多个连续空格(如
"a   b"
)—— 必须压缩,否则第二步翻转后仍残留空格,影响第三步判断 使用
size_t
做索引时,与负数比较(如
i-- >= 0
)会因无符号溢出导致死循环 调用
std::reverse
前未检查区间有效性(如
begin() + i >= begin() + j
),虽通常安全,但在空单词逻辑里可能触发 最稳妥的做法是:所有索引用
int
,每步都校验
i < n
和
j <= n
,压缩空格前先做
s.erase(0, s.find_first_not_of(' '))
类清理(但会破坏原地性)—— 所以还是推荐上面的三阶段写法。

相关文章