string类题目(上)

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具有较大的性能消耗。

本文到此结束=_=

猜你喜欢

转载自blog.csdn.net/2301_82135086/article/details/141534678