目录
1.字符串最后一个单词的长度
【思路】:这道题找到最后一个单词也就是找到最后一个空格,可以用rfind反向迭代找到最后一个空格,算出最后一个单词的大小。如果只有一个单词没有空格的话那么直接输出这个单词的长度。
但是要注意的是,在单词与单词之间的间隔,是用空格来进行的,直接用cin>>s时候,如果输入像hello nowcoder这样的字符串,s仅识别第一个单词,空格之后的字符串被识别为下一个字符串,留在了缓冲区。所以不能用cin>>s来获取字符串。
想要将空格页识别成字符串
【方法一】:
string s;
//C写法
char ch = getchar();//获取一个字符
while (ch != '\n')//循环加入s来获取字符串,遇到\n就是换行停下来
{
s += ch;
ch = getchar();
}
//getline(cin,s);
【方法2】:
string s;
//C++写法
char ch = cin.get();
while(ch!='\n')
{
s+=ch;
ch=cin.get();
}
【方法3】:
在C++的string类中,写入了一个成员方法getline,用来获取字符串的,参数1是输入流,参数2为要获取的字符串。其基本思想就是上面代码的体现。
string s;
getline(cin,s);
#include<iostream>
using namespace std;
#include <string>
int main()
{
string s;
getline(cin,s);
size_t pos=s.rfind(' ');//获取从后向前数第一个空格位置
if(pos!=string::npos)//当不等于npos(值为-1,也就代表没找到),找到了
{
string last=s.substr(pos+1,s.size()-(pos+1));//获取最后一个单词字符串
cout<<last.size()<<endl;//输出字符串大小
//cout<<s.size()-pos-1<<endl;//或者直接写这种直接算出大小
}
else
{
cout<<s.size()<<endl;
}
return 0;
}
2.字符串中的第一个唯一字符
【思路】:这道题如果让每个字符和字符串相比,那么时间复杂度是O(n^2),所以用另一种思路,设一个数组,遍历这个字符串,记录每个字符出现的次数,放入这个数组中。再次遍历整个字符串,这时相对应的字符有了自己的重复次数,当遇到第一个次数等于1的字符,返回这个字符的下标索引。
class Solution {
public:
int firstUniqChar(string s) {
//O(N)
int CountArray[26]={0};
//统计次数
for(size_t i=0;i<s.size();i++)
{
CountArray[s[i]-'a']++;
}
//找到第一个出现一次的
for(size_t j=0;j<s.size();j++)
{
if(CountArray[s[j]-'a']==1)
{
return j;
}
}
return -1;
}
};
3.仅仅反转字母
【思路】:定义两个下标begin和end,一个指向第一个位置,一个指向最后一个位置。begin从前向后遍历,直到遇到字母,end从后向前遍历,直到遇到字母,二者交换。begin和end继续遍历,直到二者相遇(begin<end),不再遍历,返回这个字符串。
class Solution {
public:
//判断是否是字符
bool IsLetter(char ch)
{
if((ch >= 'A' && ch <= 'Z') || (ch>='a'&&ch<='z'))
{
return true;
}
return false;
}
string reverseOnlyLetters(string s) {
//当遇到数字才翻转
int begin=0;
int end=s.size()-1;
while(begin<end)
{
while(begin<end && !IsLetter(s[begin]))
//这里还要判断一下begin<end,because如果这个字符串都不是字母,那么一直++下去会越界
{
++begin;
}
while(begin<end && !IsLetter(s[end]))
{
--end;
}
swap(s[begin++],s[end--]);
}
return s;
}
};
4.验证回文串
【思路】:判断是否是回文字符,定义两个下标,一个begin指向0位置,一个end指向最后一个字符,索引为s.size()-1,因为跟大小没有关系,所以可以把所有字母都转成小写或者都转成大写,再去比较。当begin遇到不是字母或数字,++begin,直到找到字母或数字;同理,当end遇到字母或数字停下,比较二者是否相等。如果不相等返回false,相等的话继续向下寻找,begin++,end--。直到begin不再小于end,搜索结束。
class Solution {
public:
//判断是否为字母或数字
bool isLetterOrNum(char ch)
{
if(ch>='a'&&ch<='z')
return true;
if(ch>='A' && ch<='Z')
return true;
if(ch>='0'&&ch<='9')
return true;
return false;
}
bool isPalindrome(string s) {
int begin = 0, end = s.size() - 1;
//全变小写
while(begin<s.size())
{
if(isLetterOrNum(s[begin]))
{
s[begin]=tolower(s[begin]);
}
++begin;
}
begin = 0;
while (begin<end)
{
while (begin<end && !isLetterOrNum(s[begin]))
{
++begin;
}
while (begin<end && !isLetterOrNum(s[end]))
{
--end;
}
if(s[begin]!=s[end])
{
return false;
}
begin++;
end--;
}
return true;
}
};
对于字母全部变小写,还可以这样写,运用范围for.
for (auto& ch : s)
{
if (ch >= 'A'&&ch <= 'Z')//大写字母的ascii码比小写字母小32
ch += 32;
}
5.字符串相加
【思路】:
单位+单位+进位,从两个数的末尾开始遍历,个位的仅为是0,所以初始化的进位extra设为0。
当两个数有一个没遍历完就继续循环,当一个数A已经遍历完,而另一个数B没有遍历完,那么设A的当前位为0,那么就是0+单位+进位。
在全局定义一个空字符串,将每个相加位数都变成字符尾插到这个空字符串当中,然而这样得到的数字是反的,最后得到的正确数字,我们再将他反转。
当两个数都遍历完,跳出循环,如果最后一个进位是1,那么再在这个字符串尾插1,除此之外,直接得到反转字符串的结果。
class Solution {
public:
string addStrings(string num1, string num2) {
int end1=num1.size()-1;
int end2=num2.size()-1;
int extra=0;
int retVal;
string sVal;
while(end1>=0 ||end2>=0)
{
int x1=0;
if(end1>=0)
{
x1=num1[end1]-'0';
end1--;
}
int x2=0;
if(end2>=0)
{
x2=num2[end2]-'0';
end2--;
}
else
{
x2=0;
}
retVal=x1+x2+extra;
if(retVal>9)
{
retVal-=10;
extra=1;
}
else
{
extra=0;
}
sVal.push_back(retVal+'0');
}
if(extra==1)
{
sVal+='1';
}
reverse(sVal.begin(),sVal.end());
return sVal;
}
};