
༺ 个人主页 · 纪念229 ༻
༒专栏目录:《算法》༒
༒专栏目录:《C++》༒
༒专栏目录:《MySQL数据库》༒
༒专栏目录:《前端开发》༒
༺世上本没有路,走的人多了自然就有了༻
本篇文章讲述的是有关string的算法题,希望对你有所帮助
题目链接:
文章目录
- 1.字符串里面最后一个单词的长度
- 2.字符串相乘
-
- 2.1、题目描述
- 2.2、核心思路
- [2.3、函数讲解:以 123 乘 45 为例](#2.3、函数讲解:以 123 乘 45 为例)
- 2.4、三个容易踩的坑
- 2.5、复杂度分析
- 2.6、结语
1.字符串里面最后一个单词的长度

对于给定的若干个单词组成的句子,每个单词均由大小写字母混合构成,单词间使用单个空格分隔。输出最后一个单词的长度。
在一行上输入若干个字符串,每个字符串代表一个单词,组成给定的句子。
除此之外,保证每个单词非空,由大小写字母混合构成
题目的意思是输入一行若干个字符串,字符串之间有空格要求我们打印出最后一个字符串的字符个数
这里有两个问题
1.它要求输入一行若干个字符串之间要有空格所以我们不能用cin去读取(利用cin去读取遇到空格就结束读取)我们需要一个可以一直读直到遇到\n(换行符)结束读取 这里我们用getline(cin,要读的字符变量)
2.要求我们得到最后一个字符串的字符个数我们知道题目给的变量是string类型的我们用rfind(' ')函数
rfind(从最后一个字符开始找从右到左找目标字符)我们直接找最后一个空格的下标我们知道下标的数据加1就是已读个数我们得到第一个字符到最后一个空格字符的个数剩余的就是最后一个字符串的个数
题目是ASM模式要求我们自己定义string类的对象
c
#include<iostream>
#include<string>
using namespace std;
// using namespace std;这个写OJ题时写上大多数类、函数都在std域里面
int main()
{
string s;
getline(cin, s);
size_t pos = s.rfind(' ');
cout << s.size() - (pos + 1);//下标为x已读个数是x + 1将总个数减已读个数就是剩余字符串的个数
return 0;
}
c
string s;
getline(cin, s);
定义一个对象用getline(cin,要读的对象)读取若干字符串
c
size_t pos = s.rfind(' ');
cout << s.size() - (pos + 1);//下标为x已读个数是x + 1将总个数减已读个数就是剩余字符串的个数
return 0;
用rfind找最后一个空格的下标来得到已读的字符(已读字符个数下标加1)(从第一个字符到最后一个空格字符的个数)
最后直接打印利用size()函数得到总字符个数减去已读个数就是最后一个字符串的字符个数
2.字符串相乘

2.1、题目描述
给定两个以字符串表示的非负整数 num1 和 num2,返回它们的乘积,但不能直接把输入转成整数计算。例如输入 num1 = "123",num2 = "45",输出 "5535"。由于数据长度可达 200 位,必须按位模拟,而模拟的对象就是小学学过的竖式乘法。
2.2、核心思路
竖式乘法的本质是三步:第一,用 num2 的每一位分别去乘 num1,得到若干中间结果;第二,把这些中间结果错位相加,第 i 位得到的结果要左移 i 位;第三,处理进位,得到最终结果。
代码对这三步各封装了一个函数:MulItem 负责一位乘多,AddItem 负责带进位的单位加法,MoveAdd 负责错位累加。
但直接按字符串顺序模拟会很别扭:乘积的进位发生在高位方向,而字符串下标是从左到右排列的。所以代码先做了一件关键的事,就是把两个字符串翻转,让低位(个位)排在前面。这样无论乘法还是加法,进位永远朝着下标增大的方向传递,一个 sign 变量就能一路带下去。
2.3、函数讲解:以 123 乘 45 为例
翻转之后,num1 变成 321,num2 变成 54,均为低位在前。
第 1 轮,取 num20 也就是 5。MulItem 计算 321 乘 5:逐位计算,第一位 3 乘 5 得 15,写入个位 5,进位 sign 记为 1;第二位 2 乘 5 再加进位 1 得 11,写入 1,进位仍为 1;第三位 1 乘 5 再加进位 1 得 6,写入 6,进位为 0。循环结束 sign 为 0 无需补位,得到 tmp 为 615,注意它是低位在前,实际表示的就是 615。
然后 MoveAdd 把 tmp 累加进 result,此时 k 等于 0,result 还是空的,直接全部拷贝进来,得到 result 为 615。
第 2 轮,取 num21 也就是 4。MulItem 计算 321 乘 4,逐位相乘并处理进位,得到 tmp 为 284,实际表示 492,再左移一位就是 4920,这个左移由 MoveAdd 的参数 k 等于 1 来实现。
MoveAdd 从下标 1 开始累加:result 原来的 6 在最低位保持不变,从下标 1 起逐位与 tmp 相加,1 加 4 得 5,5 加 8 得 13 写入 3 进位 1,下一位空看作 0,0 加 2 再加进位 1 得 3,最终 result 为 6553,低位在前。
最后收尾:先去掉高位多余的 0,result.back 是高位,用循环连续弹出,注意条件里写了 result.size 不等于 1,这是为了保住 0 这个结果,防止 0 乘任何数时被削成空串;然后翻转回来,6553 逆序得到 5535,正是正确答案。
2.4、三个容易踩的坑
第一个坑,进位的跨段传导,对应 MoveAdd 的第二个循环。tmp 加完之后如果 sign 仍为 1,进位必须继续向 result 的高位走,可能连环穿过多个 9,比如 result 高位是连续的 999,只进一位就停的实现会算错。第二个循环就是专门处理这种情况的。
第二个坑,乘法末尾的进位,对应 MulItem 循环结束之后的那段 if。像 99 乘 9 这种情况,循环结束时 sign 还有剩余,必须补 push_back 一位,否则最高位就丢了。
第三个坑,去零条件里的 size 不等于 1 不能省,否则字符串 0 会被削成空串。
2.5、复杂度分析
设两个数的长度分别为 m 和 n。时间复杂度是 O(m 乘 n),外层遍历 n 位,每一位做一次长度为 m 的乘法并累加,符合竖式乘法的代价。空间复杂度是 O(m 加 n),用于存储 result 和临时的 tmp。
2.6、结语
这份实现的特点是完全贴合手算过程:翻转解决进位方向问题,三个函数各管一段,职责清晰。经过 2000 组随机数据对拍验证,包括 0、全 9 等边界情况,逻辑全部正确。如果想进一步优化,可以试试按结果位直接累加的写法,即 res 的 i 加 j 位直接累加对应数字乘积,最后统一进位,代码更短,但思路上不如先乘后错位加直观。
题目到这就告一段落,希望对你有所帮助,感谢观看!