算法力扣刷题记录 二十三【151.翻转字符串里的单词】

news2024/11/26 3:35:52

前言

字符串篇,继续。
记录 二十三【151.翻转字符串里的单词】

一、题目阅读

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:

输入:s = "the sky is blue"
输出:"blue is sky the"

示例 2:

输入:s = "  hello world  "
输出:"world hello"
解释:反转后的字符串中不能存在前导空格和尾随空格。

示例 3:

输入:s = "a good   example"
输出:"example good a"
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。

提示:

1 <= s.length <= 104
s 包含英文大小写字母、数字和空格 ' '
s 中 至少存在一个 单词

进阶:

如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 *原地* 解法。

二、尝试实现

思路

(1)对参数s应该以空格为分隔符,分割一个一个单词。
(2)流对象能够忽略空格或‘\n’,虽然读取,但是能够忽略。

用stringstream可以完成以空格分割和忽略读取到的空格。

代码实现(测试通过)

class Solution {
public:
    string reverseWords(string s) {
        string result;	//返回值
        stringstream ss(s);	//处理字符串的流对象定义。
        string str;
        while(ss>>str){	//用>>运算符可以忽略空格,以空格为分隔符
            if(result.empty()){
                result.insert(0,str);
            }else{
                result.insert(0,str+' ');	//在新string
            }  
        }
        return result;
    }
};

进阶

在原有字符串中进行解决:

进阶思路

结合记录二十二的思路,在原有string s的后面扩容,把新倒序的单词续到原有字符串的后面。最后再把前面size长度删掉,只取size之后的。

思路示意

(1)首先不能覆盖填充,因为单词不能改变,所以覆盖填充会改变原有的单词。所以就把倒序操作放到整个size的后面
(2)扩容多大区间?

  • 统计多少个字母;假设count个字母;
  • 统计一共多少个单词。假设有n个单词,需要n-1个空格。
  • 所以扩容count+n-1。在原有size的后面。
  • 总结:s.resize(size+count+n-1);

(3)接下来,翻转单词顺序。

  • 一个指针i从s[size-1]倒着往前找单词,直到s[i] != ’ '。i不再是空格;
  • 单词内的字母没有倒序,所以得找这个单词的头。用指针j=i-1开始,往前找,直到s[j] == ’ '等于空格。s[j+1]~s[i]之间是一个单词。
  • 用一个指针k记录扩容后面的位置,要把“s[j+1]~s[i]”这个单词放在哪个位置?k初始是size。从s[size]开始。
  • 空格处理:
    • 如果是倒数第一个单词,那么前面不需要有空格;如果不是倒数第一个单词,就要有空格。

代码实现(测试通过)

可以查看注释解释

class Solution {
public:
        string reverseWords(string s) {
        int size = s.size();
        int count = 0;  //统计有多少个字母
        int num = 0;    //统计多少个单词
        for(int i = 0;i < size;i++){  
            if(s[i] != ' '){	//挨个遍历原来的size,不是空格时,count可以++
                count++;
                if(i+1 < size && s[i+1]==' ' ){	//如果下一位是空格,说明是一个单词,所以num++
                    num++;
                }else if(i == size-1){	//如果s[size-1]不是空格,最后一个单词也要加上。
                    num++;
                }
            }
        }

        s.resize(size+count+num-1);//扩容
        //在扩容的区间开始翻转单词顺序
        int k = size;
        int phase = 0;
        //倒着往前找
        for(int i =size-1;i >=0;){
            if(s[i] != ' '){	//遇到一个单词的末尾字母
                int j = i-1;
                int subchar = 1;
                phase++;		//记录当前翻转的第几个单词
                for(j;j >=0;j--){	//找这个单词多长,for结束后s[j+1]是这个单词的首字母
                    if(s[j] == ' '){
                        break;
                    }
                    subchar++;	//记录单词多长
                }
                if(phase != 1){	//如果不是倒数第一个单词,在后面放单词之前先加一个空格。
                    s[k++] = ' ';
                }
                for(int m = 0;m < subchar;m++){	//单词字母没有倒转,所以正向的顺序把字母放置好。
                    s[k++] = s[j+m+1];
                }
                i = j;
                
            }
            i--;
        }
        s.erase(0,size);	//最后删除从0开始,长度为size的部分。把原有部分删除。
        return s;
    
    }
};

总结:两种方法都解决了。这种扩容可以认为是原地操作。


三、代码随想录学习

学习内容

主要看思路区别和实现区别:
(1)用split库函数,分割string s , 再用一个新字符串。C++里面没有split的函数。要么就是C风格的strtok函数,在< cstring >中,原来的string.h。
(2)因为想到reverse翻转会直接把字母翻转,就没再考虑;其实可以reverse整个string s,再把每个单词reverse回来。
(3)处理空格:多余的空格要删掉,如果不是第一个单词,前面还要留一个空格。(删除空格,也是删除元素,string可以像数组一样操作,所以用双指针法)

代码实现

class Solution {
public:
void phaseReverse(string& s,int start ,int end){	//库函数reverse使用类型iterator。
            if(start > s.size() || end < 0){
                return;
            }
            for(int i = start,j = end-1;i < j;i++,j--){ //左闭右开
                swap(s[i] ,s[j]);
            }
        }
    string reverseWords(string s) {
        //删除空格
        int fast = 0;
        int slow = 0;
        for(;fast < s.size();fast++){
            if(s[fast] != ' '){		//当遇到不该删的字符。如果没有这个判断,单词之间的空格没有删掉。
                if( slow != 0){
                    s[slow++] = ' ';//先给空格再slow++
                }
                while(fast < s.size() && s[fast] != ' '){	//必须有 < s.size() 判断,没有会越界。
                    s[slow] = s[fast];
                    fast++;
                    slow++;
                }
            }
        }

        s.resize(slow);
        reverse(s.begin(),s.end());
        //在翻转每个单词
        for(int i = 0,j = 0;j <= s.size();j++){	//因为phaseReverse左闭右开,所以j <= ,带等号。
            if(s[j] == ' ' || j == s.size()){
                phaseReverse(s,i,j);
                i = j+1;
            }
        }
        return s;
    }
};

总结

(1)用一个新string,用stringstream处理。
(2)扩容原来的string s,倒着往前找单词,放到后面,最后把前面长size的内容erase。
(3)先删除空格(双指针法),再reverse整体,再翻转某个单词。

(欢迎指正,转载表明出处)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1875902.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python报错】已解决 ModuleNotFoundError: No module named ‘transformers‘

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 ModuleNotFoundError: No module named ‘transformers’ 是一个常见的错误&#xff0c;它表明你的Python环境中没有安装t…

2023阿里巴巴全球数学竞赛决赛中的LLM背景题解析(应用与计算数学部分第2题)...

早点关注我&#xff0c;精彩不错过&#xff01; 最近闹得沸沸扬扬的姜萍事件果真又成了世界就是个草台班子的有力论据。无论真相如何&#xff0c;各自心怀鬼胎&#xff0c;自有策略的合作看起来就一定是一场场的闹剧。 无意作过多评论&#xff0c;也绝不妄下言论&#xff0c;就…

Unity之自定义Text组件默认属性值

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之自定义Text组件默认属性值 TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取&#xff01;…

硬件实用技巧:刚挠板pcb是什么

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140060334 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

SQLServer 表值构造函数 (Transact-SQL)

在 SQL Server 中&#xff0c;表值构造函数&#xff08;Table Value Constructor, TVC&#xff09;是一种用于在单个语句中插入多行数据到表中的语法。它允许你以行内表值表达式&#xff08;row-valued expression&#xff09;的形式指定多行数据&#xff0c;并将这些数据作为一…

基于weixin小程序周边美食系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;美食店铺管理&#xff0c;菜品分类管理&#xff0c;标签管理&#xff0c;菜品信息管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;美食店铺&#x…

ROS2使用Python创建服务提供者、消费者

1.创建服务提供者 ros2 pkg create example_service_rclpy --build-type ament_python --dependencies rclpy example_interfaces --node-name service_server_02 service_server_02.py 代码 #!/usr/bin/env python3 import rclpy from rclpy.node import Node # 导入接口 …

办公软件WPS与Office的区别

临近计算机考试很多同学在纠结我是报wps好&#xff1f;还是ms office好&#xff1f;下面就来详细说说。 1、wps属于国内金山公司的办公软件&#xff0c;里面包含word、Excel和PPT。考试是2021年开始的&#xff01; 2、MS&#xff08;Microsoft 微软&#xff09; office属于美…

web安全渗透测试十大常规项(一):web渗透测试之深入JAVA反序列化

渗透测试之PHP反序列化 1. Java反序列化1.1 FastJson反序列化链知识点1.2 FastJson反序列化链分析1.3.1 FastJson 1.2.24 利用链分析1.3.2 FastJson 1.2.25-1.2.47 CC链分析1.3.2.1、开启autoTypeSupport:1.2.25-1.2.411. Java反序列化 1.1 FastJson反序列化链知识点 1、为什…

线程池技术实现及参数工作流程原理

一.什么是线程池 线程池其实就是一种多线程处理形式&#xff0c;处理过程中可以将任务添加到队列中&#xff0c;然后在创建线程后自动启动这些任务。这里的线程就是我们前面学过的线程,这里的任务就是我们前面学过的实现了Runnable或Callable接口的实例对象。 为什么使用多线程…

【RT摩拳擦掌】RT云端测试之百度天工物接入构建(设备型)

【RT摩拳擦掌】RT云端测试之百度天工物接入构建&#xff08;设备型&#xff09; 一&#xff0c; 文档介绍二&#xff0c; 物接入IOT Hub物影子构建2.1 创建设备型项目2.2 创建物模型2.3 创建物影子 三&#xff0c; MQTT fx客户端连接云端3.1 MQTT fx配置3.2 MQTT fx订阅3.3 MQT…

修改docker中mongodb容器的时区

假设容器名称为mongodb&#xff0c;设置时区为上海时区的命令为&#xff1a; docker exec -it mongodb bash -c "ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone"验证时区更改&#xff1a; docker e…

Eigen中关于四元数的常用操作

四元数&#xff08;Quaternion&#xff09;是一种数学工具&#xff0c;广泛用于计算机图形学、机器人学和物理模拟中&#xff0c;特别适合处理三维旋转。Eigen库是一个高性能的C数学库&#xff0c;提供了丰富的线性代数功能&#xff0c;其中就包括对四元数的支持。 1. 为什么选…

element ui form 表单验证

表单验证方法 在el-form元素上总体设置校验规则rules&#xff0c;下面是官方案例 <el-form :model"ruleForm" :rules"rules" ref"ruleForm" label-width"100px" class"demo-ruleForm"><el-form-item label"…

基于Java游戏售卖网站详细设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

从零开始学Spring Boot系列-集成Spring Security实现用户认证与授权

在Web应用程序中&#xff0c;安全性是一个至关重要的方面。Spring Security是Spring框架的一个子项目&#xff0c;用于提供安全访问控制的功能。通过集成Spring Security&#xff0c;我们可以轻松实现用户认证、授权、加密、会话管理等安全功能。本篇文章将指导大家从零开始&am…

Qt Creator创建一个用户登录界面

目录 1 界面设计 2 代码 2.1 登录界面 2.2 注册界面 2.3 登陆后的界面 3 完整资源 这里主要记录了如何使用Qt Creator创建一个用户登录界面&#xff0c;能够实现用户的注册和登录功能&#xff0c;注册的用户信息存储在了一个文件之中&#xff0c;在登录时可以比对登录信息…

模型预测控制:线性MPC

模型预测控制&#xff1a;线性MPC 模型预测控制&#xff08;Model Predictive Control, MPC&#xff09;是一种广泛应用于工业过程控制和自动驾驶等领域的先进控制技术。MPC通过在线解决优化问题来计算控制输入&#xff0c;从而实现系统的最优控制。本文将介绍线性MPC的系统模…

C# 实现websocket双向通信

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C# &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff…

【地理库 Turf.js】

非常全面的地理库 &#xff0c; 这里枚举一些比较常用&#xff0c;重点的功能&#xff0c; 重点功能 提供地理相关的类&#xff1a;包括点&#xff0c;线&#xff0c;面等类。 测量功能&#xff1a;点到线段的距离&#xff0c;点和线的关系等。 判断功能&#xff1a; 点是否在…