【string题解 C++】字符串相乘 | 翻转字符串III:翻转单词

news2024/11/18 14:28:42

字符串相乘

题面

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

示例 1:

输入: num1 = "2", num2 = "3" 输出: "6" 示例 2:

输入: num1 = "123", num2 = "456" 输出: "56088"

错误记录

我一开始的思路是:先把俩字符串转化成整数,然后相乘,结果再转化成字符串返回回去。然后挣扎了很久,每次测试都没问题,一提交就报错。后来我仔细看了下题面,发现人家早就说明了:“不能使用任何内置的 BigInteger 库或直接将输入转换为整数。”

所以这道题要的就是你去模拟乘法的计算过程,并且计算过程的数字要以字符的形式存进string中。

Way1 拆分成“先乘后加”

思路

现在目的明确,完成两个Part:

1.遍历两个字符串,将整个的乘法拆分成一部分一部分的乘积。

2.将这些乘积相加,即写一个字符串相加的函数。

实现

class Solution {
public:
    string multiply(string num1, string num2) {
        if(num1=="0"||num2=="0"){   //如果有一个被乘数是0,那结果直接返回0
            return "0";
        }
        int n1=num1.size(),n2=num2.size();   
        string ret,combine_ret;
        for(int i=n1-1;i>=0;i--){   
            //每次都要把上一次的更新一下
            ret.clear();
            int add_num=0;    //用于保存进位
            for(int j=n2-1;j>=0;j--){
                int tmp=(num1[i]-'0')*(num2[j]-'0')+add_num;
                int present_num=tmp%10;     //当前位
                ret.insert(ret.begin(),present_num+'0');
                add_num=tmp/10;
            }
            
            if(add_num){      //如果还有剩余的add_num,别忘了进位  
                ret.insert(ret.begin(),add_num+'0');
            }
            
            int add_num_of_zero=n1-1-i;   //补0
            while(add_num_of_zero){
                ret.push_back('0');
                add_num_of_zero--;
            }
            combine_ret=addString(combine_ret,ret);
        }
        return combine_ret;
    }
    
    string addString(string s1,string s2){   //这里字符串相加 采用的是补0的思路,很实用
        int n1=s1.size(),n2=s2.size();
        string StrRet;
        //通过在前面补0的方法,让n1和n2位数对齐
        while(n1>n2){
            s2.insert(s2.begin(),'0');
            n2++;
        }
        while(n2>n1){
            s1.insert(s1.begin(),'0');
            n1++;
        }
​
        int add_num=0;
        for(int i=n1-1;i>=0;i--){
            int tmp=(s1[i]-'0')+(s2[i]-'0')+add_num;
            add_num=tmp/10;
            StrRet.insert(StrRet.begin(),tmp%10+'0');
        }
      
        if(add_num){       //如果还有剩余的add_num,别忘了进位
            StrRet.insert(StrRet.begin(),add_num+'0');
        }
        return StrRet;
    }
};

时空复杂度分析

时间复杂度为O(n1*n2),其中n1、n2分别是num1、num2的长度。

空间复杂度O(1)

反思

1.每次循环开始前 ,别忘了刷新变量!要再设回初始值。

2.字符串相加,用补0的思路,很好用。先将俩字符串的位数 用0补得整齐,后面就很好计算了。

3.最常犯的错误是:没把数字转化成askii码存进字符串

for(int i=n1-1;i>=0;i--){
            int tmp=AddNum+(s1[i]-'0')+(s2[i]-'0');
            ret.insert(ret.begin(),tmp%10);   //应为tmp%10+'0'
            AddNum=tmp/10;
        }

4.这个思路的亮点在于 拆分成先乘后加 和 补0。

Way2 用数组

思路

1.开大小为n1+n2的数组(记得初始化为0)。

因为两数相乘,乘积的位数 是不会超过 被乘数的位数之和的,所以这个大小一定够用了。

2.从右往左遍历被乘数的每个位数,结果挨个放进数组里。

3.把数组的数存进字符串,同时要考虑进位。

实现

class Solution {
public:
    string multiply(string num1, string num2) {
        if(num1=="0"||num2=="0"){
            return "0";
        }
        int n1=num1.size(),n2=num2.size();
        int NumArr=n1+n2;
        int*arr=new int[NumArr]();  //注意这种写法 可以初始化为0
​
        int k=NumArr-1;
        for(int i=n1-1;i>=0;i--){
            int CopyK=k;     
            for(int j=n2-1;j>=0;j--){
                int tmp=(num1[i]-'0')*(num2[j]-'0');
                arr[k--]+=tmp;
            }
            k=CopyK-1;
        }
​
        //把数组内容存进字符串
        string ret;
        int AddNum=0;
        for(int i=NumArr-1;i>=0;i--){
            //进位
            AddNum=arr[i]/10;
            if(i>0){
            arr[i-1]+=AddNum;    //这里要小心,i-1是很容易越界的!所以要加个条件判断 
            }
​
            ret.insert(ret.begin(),arr[i]%10+'0');
        }
        if(AddNum){
            ret.insert(ret.begin(),AddNum+'0');
        }
        delete[] arr;
        for(int i=0;i<NumArr;i++){
            if(ret[i]!='0'){
                return ret.substr(i);
            }
        }
        return ret;
    }
};

时空复杂度分析

时间复杂度为O(n1*n2+n1+n2),n1、n2分别为num1、num2的大小

空间复杂度为O(n1+n2)

翻转字符串III:翻转字符串中的单词

题面

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例 1:

输入:s = "Let's take LeetCode contest" 输出:"s'teL ekat edoCteeL tsetnoc" 示例 2:

输入: s = "God Ding" 输出:"doG gniD"

错误记录

第一次写的时候,报执行出错,修改了好久,也没发现错误:

class Solution {
public:
    void swap(string& s,int left,int right){
        while(left!=right){
        std::swap(s[left],s[right]);
        left++;
        right--;
        }
    }
    string reverseWords(string s) {
        int num=s.size();
        int front_i=0;
        for(int i=0;i<num;i++){
            if(s[i]==' '){
                if(front_i!=0){
                    front_i+=1;
                }
                swap(s,front_i,i-1);
                front_i=i;  
            }
        }
        return s;
    }
};

报错:

后来终于揪出来BUG了,在这里:

void swap(string& s,int left,int right){
        while(left!=right){       //这里不能用!=,得用<
        std::swap(s[left],s[right]);
        left++;
        right--;
        }
    }

当string的大小是偶数个时,!= 会导致left和right刚好错过。

果然是细节决定成败!!

思路1 遍历找单词

这题的思路蛮简单的:遍历一遍字符串,遇到单词,就把整个单词swap一下。

至于怎么找到单词?

可以通过空格的位置来划分单词。也可以遍历的时候记录下单词的起始位置。这两种找单词的方法都来实现一下。

实现

这种思路下的两种实现方式:

第一种:

 
class Solution {
public:
    void swap(string& s,int left,int right){
        while(left<right){
        std::swap(s[left],s[right]);
        left++;
        right--;
        }
    }
    string reverseWords(string s) {
        int num=s.size();
        int front_i=0;
        for(int i=0;i<num;i++){
            if(s[i]==' '){      //找到空格的位置
                if(front_i!=0){
                    front_i+=1;
                }
                swap(s,front_i,i-1);
                front_i=i;  
            }
        }
        //处理下最后一个词
        if(front_i!=0){
            front_i+=1;
        }
        swap(s,front_i,num-1);
        return s;
    }
};

第二种:这种方法我第一次没写出来,那个循环给我绕晕了。这种方法挺好的,得多写几遍!!!

class Solution {
public:
    string reverseWords(string s) {
        int num=s.size();
        int i=0;
        while(i<num){
            int start=i;
            while(i<num&&s[i]!=' '){   //注意看这个循环条件!!要加上i<num,保证安全
            i++;
            }  
            //当出了循环,str[i]就是空格
            int left=start;
            int right=i-1;
            while(left<right){
                swap(s[left],s[right]);
                left++;
                right--;
            }
​
            while(i<num&&s[i]==' '){  
                i++;
            }
        }
        return s;
    }
};

反思:

第二种思路我当时没写出来,问题就出在那个大循环while(i<num){}里,我当时一上来就把框架搭好了:

while(i<num)
{
    i++;
}

这个框架太经典了,结果限制住了我的思路。实际上,我不应该先把i++;写上的,后面得把这个循环多写几遍,多体会一下。

然后就是要注意,大while()里包小while(),小while()加上大while()的判断条件,会更安全,不容易越界。

思路2 暴力解法

思路1里,我们是手动翻转字符串的,但实际上可以直接用库里的reverse、find函数。

思路2则不用遍历字符串的每一个字符,而是用find找到空格,,然后从空格的后一个 接着去找 下一个空格。

当没有空格时,说明是最后一个单词,翻转,然后break跳出循坏。

注意,这种写法,循环里也没有经典的"i++;",所以不要一写循环就把i++;给添上,不要 被习惯限制住思路!

实现

class Solution {
public:
    string reverseWords(string s) {
        int num=s.size();
        int i=0;
        while(i<num){
            size_t pos=s.find(' ',i);   //注意这里用size_t
            if(pos!=string::npos){
                reverse(s.begin()+i,s.begin()+pos);  //因为是从i开始找的,所以要加i
                i=pos+1;                           //现在要从空格的下一位开始找
            }                                     //注意reverse是左闭右开,右边是开区间
            else{
                reverse(s.begin()+i,s.end());   //没有空格了,说明这已经是最后一个单词了
                break;
            }
        }
        return s;
    }
};

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

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

相关文章

基本微信小程序的电影票务系统-电影票预订系统

项目介绍 在传统的模式下&#xff0c;电影购票需要到当地的影院进行线下购票&#xff0c;既浪费时间&#xff0c;又消耗人力。线上购票可以满足消费者查看电影信息及购买电影票的需求&#xff0c;在一定程度上降低经济和时间成本[9]。目前已有一些手机app可以线上购票&#xf…

优化|优化处理可再生希尔伯特核空间的非参数回归中的协变量偏移

原文&#xff1a;Optimally tackling covariate shift in RKHS-based nonparametric regression. The Annals of Statistics, 51(2), pp.738-761, 2023.​ 原文作者&#xff1a;Cong Ma, Reese Pathak, Martin J. Wainwright​ 论文解读者&#xff1a;赵进 编者按&#xff1a; …

无名管道和有名管道

进程间通信的几种方式 无名管道&#xff08;pipe&#xff09; 无名管道&#xff08;Unnamed Pipe&#xff09;是一种在进程间进行单向通信的机制。它可以用于父进程与子进程之间的通信&#xff0c;或者同一父进程中不同子进程之间的通信。无名管道是一种特殊的文件&#xff0…

【(数据结构) —— 顺序表的应用-通讯录的实现】

&#xff08;数据结构&#xff09;—— 顺序表的应用-通讯录的实现 一.通讯录的功能介绍1.基于动态顺序表实现通讯录(1). 功能要求(2).重要思考 二. 通讯录的代码实现1.通讯录的底层结构(顺序表)(1)思路展示(2)底层代码实现(顺序表&#xff09; 2.通讯录上层代码实现(通讯录结构…

IEDA 自动生成类注释和方法注释

1. 新建类&#xff0c;自动生成类注释的模板配置 File->Settings->Editor->File and Code Templates->Class /*** Description: TODO* Author: LT* Date: ${YEAR}-${MONTH}-${DAY}* Version:V3.5.6*/2. 通过快捷键&#xff0c;添加类注释和方法注释的模板设置 类…

六轴传感器 SH3001

SH3001简介 SH3001是Senodia公司生产的一款六轴姿态传感器&#xff0c;可测量芯片自身X、Y、Z轴的加速度以及角速度参数&#xff0c;通过姿态融合&#xff0c;进而得到姿态角。 三轴加速度计&#xff08;Accelerometer&#xff09;&#xff1a;测量X、Y、Z轴的加速度。 三轴陀…

C++基础入门详解(一)

文章目录 前言命名空间展开命名空间使用C官方命名空间中的输入输出IO流输入输出的使用方法 缺省参数半缺省 函数重载 “你总以为机会无限&#xff0c;所以不珍惜眼前人” 前言 提到C&#xff0c;大部分人都想到的是复杂的语法和大量的规则&#xff0c;相对于java和python等语言…

基于YOLOv8模型的绵羊目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8模型的绵羊目标检测系统可用于日常生活中检测与定位车辆目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算法训练数据集…

基于simulink的单相光伏系统并网储能控制仿真

本仿真涉及到&#xff1a;基于电导增量法的最佳功率点跟踪算法、蓄电池恒流_恒压充电算法、光伏逆变器并网算法、双向&#xff08;同步&#xff09;DCDC电路设计等知识。 辐照度变化曲线&#xff1a; 模拟仿真&#xff0c;低辐照度情况&#xff0c;蓄电池与光伏逆变器共同向…

软件项目管理实践指南:有效规划、执行和控制

软件项目管理是使软件产品、应用程序和系统成功交付的重要规程。它有助于确保软件在预算内按时开发&#xff0c;同时满足客户的质量和功能需求。 软件项目管理是管理软件项目生命周期的一种有组织的方法&#xff0c;包括计划、开发、发布、维护和支持。它是在满足客户需求的同时…

python:绘制回归预测结果真实值和预测值之间的散点密度图

作者:CSDN @ _养乐多_ 对博客《python:使用卷积神经网络(CNN)进行回归预测》中的,回归预测结果真实值和预测值之间的散点密度图升级了一下。 如下图所示, 文章目录 一、完整代码二、参考一、完整代码 def plot(y_test, y_test_predict, method):d

SAP MM学习笔记34 - 请求书照合中的支付保留(发票冻结)

上次学习了 请求书照合中 如何修改 带勘定设定Category的发票&#xff0c;并举了 K&#xff1a;原价Center 的例子。 SAP MM学习笔记33 - 请求书照合中修改 带勘定设定Category&#xff08;科目分配&#xff09;的发票_东京老树根的博客-CSDN博客 日月如梭&#xff0c;倏忽之间…

JMeter性能测试,完整入门篇

1. Jmeter简介 Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件。相比Loadrunner而言&#xff0c;JMeter小巧轻便且免费&#xff0c;逐渐成为了主流的性能测试工具&#xff0c;是每个测试人员都必须要掌握的工具之一。 本文为JMeter性能测试完整入门篇&…

【【萌新的SOC学习之AXI DMA环路测试介绍】】

萌新的SOC学习之AXI DMA环路测试介绍 AXI DMA环路测试 DMA(Direct Memory Access&#xff0c;直接存储器访问)是计算机科学中的一种内存访问技术。它允许某些计算机内部的硬件子系统可以独立地直接读写系统内存&#xff0c;而不需中央处理器&#xff08;CPU&#xff09;介入处…

【atoi函数详解】

文章目录 一. 什么是atoi函数二. 模拟实现函数atoi三. 总结atoi 一. 什么是atoi函数 atoi函数是将常量字符串转化为整数 int atoi(const char str);* 注意&#xff1a;该函数的返回值为int&#xff0c;所以不能超过int范围&#xff0c;如果数字很大超过就会截断&#xff0c;返…

手搭手Mybatis-Plus数据迁移至TDSQL

环境介绍 技术栈 springbootmybatis-plusdruidbaomidoumysqloracle 软件 版本 mysql 8 IDEA IntelliJ IDEA 2022.2.1 JDK 1.8 Spring Boot 2.7.13 mybatis 2.3.1 Navicat测试连接TDSQL 开启访问外网 IDEA环境搭建 pom.xml所需依赖 <dependencies><dep…

计算机毕业设计选什么题目好?springboot 试题库管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

element ui el-table表格复选框,弹框关闭取消打勾选择

//弹框表格复选框清空 this.$nextTick(()>{this.$refs.table.clearSelection();})<el-table ref"table" v-loading"crud.loading" :header-cell-style"{ color: #FFF, background: #333 }":cell-style"{ color: #FFF, background: #3…

【Java 进阶篇】JavaScript 日期和时间详解

JavaScript是一种强大的编程语言&#xff0c;它不仅可以用于处理文本和数字&#xff0c;还可以处理日期和时间数据。在本篇博客中&#xff0c;我们将深入探讨JavaScript中日期和时间的处理方式。不管你是在网页开发、移动应用开发&#xff0c;还是服务端开发&#xff0c;处理日…

Linux 查看CPU架构及内核版本

涉及arch命令和/proc/version文件 1 查看CPU架构 有些软件的安装需要和CPU架构相匹配&#xff0c;如JDK等等&#xff0c;所以需要确定主机的CPU架构类型。可使用命令arch查看Linux系统的CPU架构&#xff0c;如下&#xff1a; arch 12 查看内核版本 文件/proc/version中包含系…