string类题目
题目来源(Leetcode)
题目一:仅仅反转字母
分析
这个反转的特点在于只反转字母,不反转特殊字符。
法一:如果我们让一个正向迭代器指向第一个字符,让一个反向迭代器指向最后一个字符,会有一个问题,它们在相遇的时候,两个迭代器无法比较。迭代器像指针,但不一定是指针。
我们会发现这俩类型都不一样,无法比较。
同时,如果用*it==*rit
来判断两者相遇是不行的,因为有可能二者在移动的半途就遇到指向字符相等的情况。
两个都用正向迭代器或反向迭代器,是可以的。一个++,一个–。
但既然如此,不如直接用下标,不用迭代器。其次,范围for也解决不了这个问题。
因为范围for只能正着遍历,不能倒着遍历。
当然这几种可行的方法里没有绝对的好与坏。
这里用一下下标法:
class Solution {
public:
bool isLetter(char ch)
{
if(ch>='a'&&ch<='z')
return true;
if(ch>='A'&&ch<='Z')
return true;
return false;
}
string reverseOnlyLetters(string s) {
int left=0,right=s.size()-1;
while(left<right)
{
while(left<right&&!isLetter(s[left]))//否则没有字母,left一直走直接越界
{
++left;
}
while(left<right&&!isLetter(s[right]))
{
--right;
}
swap(s[left++],s[right--]);//这里不++和--的话会死循环
}
return s;
}
};
题目二:字符串中的第一个唯一字符
分析
每个字符都和后面其他字符去比较的方法,时间复杂度太差,怎么优化到O(n)呢?
可以用计数排序法。
可以统计每个字符出现的次数。
a的ASCII是97,a映射0,b映射1,c映射2,ch-'a’算出相对值,直接就映射到对应位置了,这个字符出现几次就++几次。
还有一个问题是,唯一字符可能有多个,但是我们要求的是第一个。
参考代码:
class Solution {
public:
int firstUniqChar(string s) {
int count[26]={0};
//统计次数
for(auto ch:s)
{
count[ch-'a']++;
}
for(size_t i = 0;i<s.size();++i)
{
if(count[s[i]-'a']==1)
return i;
}
return -1;
}
};
这个时间复杂度为O(n),因为我们就遍历了两遍字符串。
题目三:字符串相加
分析
整型就可以相加,但是在一些科研中,整数可能太大了,计算机存不下。long long存到2的64次方,但是可能还是不够大。所以就存到字符串中进行运算。大数运算。
string提供了一套库,从此我们不太需要去用atoi和itoa了:
这个函数可以把字符串转成整型。
这个函数则可以把各种类型转成字符串。
但是我们把给我们的字符串通过stoll转成整型计算完再转回字符串的方式只能对不那么大的数据有用,所以我们不能想着去使用这个捷径。
那么要怎么解决这道题呢?
首先我们要去取这个字符串里的字符,而且要从低位去取,也就是倒着去取。
1024字节是1KB,如果整数的长度是100w(100w长度的整数大小得多大?8个位就已经是亿了,10个位百亿),就才1M空间左右。
最后我们需要往string对象中头插:
single character (6):
iterator insert (iterator p, char c);
代码参考:
class Solution {
public:
string addStrings(string num1, string num2) {
string str;
int end1=num1.size()-1,end2=num2.size()-1;
int next=0;//进位
while(end1>=0 || end2>=0)
{
int val1=end1>=0?num1[end1--]-'0':0;
int val2=end2>=0?num2[end2--]-'0':0;
int ret=val1+val2+next;//每次把进位加上
next=ret/10;
ret=ret%10;
str.insert(str.begin(),'0'+ret);//头插到字符串
}
if(next==1)//处理没处理的进位
str.insert(str.begin(),'1');
return str;
}
};
但是用头插,时间复杂度会较差,所以用尾插:
这个+=运算符重载就是尾插,底层调用的就是pushback。可以尾插一个字符、一个string。
尾插完后需要逆置,string类中没有,但是STL有:
传的区间必须是左闭右开。
class Solution {
public:
string addStrings(string num1, string num2) {
string str;
int end1=num1.size()-1,end2=num2.size()-1;
int next=0;//进位
while(end1>=0 || end2>=0)
{
int val1=end1>=0?num1[end1--]-'0':0;
int val2=end2>=0?num2[end2--]-'0':0;
int ret=val1+val2+next;//每次把进位加上
next=ret/10;
ret=ret%10;
str+=('0'+ret);
}
if(next==1)//处理没处理的进位
str+='1';
//逆置-STL
reverse(str.begin(),str.end());
return str;
}
};
头插如果遇上较大的数据可能无法通过,insert具有较大的性能消耗。
本文到此结束=_=