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

发布时间 - 2026-01-22 00:00:00    点击率:
必须用双指针而非std::reverse直接反转,因为后者会使单词内部字母翻转;双指针法通过整体反转、单词内反转、清理多余空格三步实现单词顺序反转且单词内字符不变,空间复杂度O(1)。

为什么要用双指针而不是 std::reverse

直接对整个字符串调用 std::reverse 会把单词内部字母也翻转,比如 "hello world" 变成 "dlrow olleh",而题目要的是单词顺序反转、单词内字符不变——即变成 "world hello"。所以必须先按空格切分逻辑,再逐段反转,双指针法正好在原地完成这个过程,不依赖额外容器(如 std::vector<:string>),空间复杂度控制在 O(1)(不计输入字符串本身)。

双指针法三步走:整体反转 + 单词内反转 + 清理多余空格

标准做法是三个阶段,缺一不

可,否则结果错乱:

  • 第一遍:用两个指针从首尾向中间,std::swap 整个字符串 —— 让单词顺序倒过来,但每个单词也反了
  • 第二遍:扫描字符串,对每个连续非空格子串(即一个单词),用局部双指针把它再翻回来
  • 第三遍:处理开头、结尾和中间多个空格的问题;若要求“单词间仅一个空格”,需额外原地压缩(否则输出含冗余空格)

注意:C++ 中 std::string 支持随机访问和修改,所以所有操作可原地进行;但若传入的是 const std::string&,需先拷贝一份可变副本。

std::string 原地反转单词顺序的完整实现

以下代码实现「单词顺序反转 + 单词内字符不变 + 单词间仅保留一个空格」,不含额外库依赖(除 ):

void reverseWords(std::string& s) {
    // 步骤1:整体反转
    std::reverse(s.begin(), s.end());
// 步骤2:逐个单词反转(跳过空格,定位每个单词区间)
int n = s.length();
int i = 0;
while (i zuojiankuohaophpcn n) {
    if (s[i] != ' ') {
        int j = i;
        while (j zuojiankuohaophpcn 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 zuojiankuohaophpcn n; ++read) {
    if (s[read] != ' ') {
        if (write != 0) s[write++] = ' '; // 单词间加空格(首个单词前不加)
        while (read zuojiankuohaophpcn 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 和 j ,压缩空格前先做 s.erase(0, s.find_first_not_of(' ')) 类清理(但会破坏原地性)—— 所以还是推荐上面的三阶段写法。


# word  # go  # c++  # 为什么  # String  # const  # 字符串  # int  # 循环  # 指针  # 的是  # 第三步  # 多个  # 切分  # 但在  # 适用于  # 把它  # 要用  # 不含  # 会使 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 桂林网站制作公司有哪些,桂林马拉松怎么报名?  微信小程序 闭包写法详细介绍  香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化  JavaScript如何实现继承_有哪些常用方法  如何用JavaScript实现文本编辑器_光标和选区怎么处理  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  如何在腾讯云免费申请建站?  深圳网站制作的公司有哪些,dido官方网站?  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  Linux网络带宽限制_tc配置实践解析【教程】  Laravel distinct去重查询_Laravel Eloquent去重方法  制作企业网站建设方案,怎样建设一个公司网站?  如何用景安虚拟主机手机版绑定域名建站?  高性能网站服务器部署指南:稳定运行与安全配置优化方案  如何用虚拟主机快速搭建网站?详细步骤解析  Laravel Octane如何提升性能_使用Laravel Octane加速你的应用  如何在七牛云存储上搭建网站并设置自定义域名?  Laravel如何配置中间件Middleware_Laravel自定义中间件拦截请求与权限校验【步骤】  python中快速进行多个字符替换的方法小结  高防服务器如何保障网站安全无虞?  Laravel怎么实现验证码(Captcha)功能  如何在橙子建站中快速调整背景颜色?  如何挑选高效建站主机与优质域名?  佛山企业网站制作公司有哪些,沟通100网上服务官网?  音响网站制作视频教程,隆霸音响官方网站?  零基础网站服务器架设实战:轻量应用与域名解析配置指南  Laravel如何记录自定义日志?(Log频道配置)  Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践  Laravel Admin后台管理框架推荐_Laravel快速开发后台工具  黑客入侵网站服务器的常见手法有哪些?  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】  如何快速上传建站程序避免常见错误?  JavaScript如何实现路由_前端路由原理是什么  Laravel如何从数据库删除数据_Laravel destroy和delete方法区别  Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】  Laravel模型关联查询教程_Laravel Eloquent一对多关联写法  如何在万网利用已有域名快速建站?  Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】  高防服务器租用首荐平台,企业级优惠套餐快速部署  Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?  mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?  如何挑选优质建站一级代理提升网站排名?  laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法  DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解  怎样使用JSON进行数据交换_它有什么限制  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】