C++算法(11)字符串

1.最长公共前缀

14. 最长公共前缀 - 力扣(LeetCode)

这道题在最好的情况下的时间复杂度似乎也只能到

**方法一:**前两个字符串处理后找出最长公共前缀(用一个指针去遍历观察情况,循环条件是用min函数求出较短字符串的长度),再把找出的最长公共前缀当作一个新字符串和下一个字符串处理再找出最长公共前缀......一直循环这个过程直至全部字符串都处理完。

代码如下:

cpp 复制代码
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) 
    {
        int n=strs.size();
        string tmp=strs[0];
        for(int i=1;i<n;i++)
        {
            int j=0;
           for(;j<min(tmp.size(),strs[i].size());j++)
            {
                if(strs[i][j]!=tmp[j])
                {
                    break;
                }
            }
            tmp=tmp.substr(0,j);
        }
        return tmp;
    }
};

**方法二:**所有字符串同时比较,对于同一个下标,对所有字符串都遍历一遍看该字符串在这个下标的情况,当下标值等于该字符串的字数或字符不一样,即可返回最长公共前缀,若全部循环都通过,则返回其中一个字符串。

代码如下:

cpp 复制代码
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) 
    {
        for(int i=0;i<strs[0].size();i++)
        {
            char tmp=strs[0][i];
            for(int j=1;j<strs.size();j++)
            {
                if(i==strs[j].size()||strs[j][i]!=tmp)
                {
                    return strs[0].substr(0,i);
                }
            }
        }
        return strs[0];
    }
};

2.最长回文子串

5. 最长回文子串 - 力扣(LeetCode)

这道题的思路是遍历字符串,把遍历到的每一个字符认为是回文子串的中心,从该下标开始向两边走,确定最长的回文子串,并判断是否要更新数据(起始位置、长度),对于每一个中心字符,其有可能是中心字符中的其中一个(回文子串是偶数长度),也有可能是唯一一个(回文字串是奇数长度),所以对于每一个下标,要做两次判断,一次奇数一次偶数。

cpp 复制代码
class Solution {
public:
    string longestPalindrome(string s) 
    {
        int n=s.size();
        int len1=1,begin=0;
        for(int i=0;i<n;i++)
        {
            int left=i-1,right=i+1;
            while(left>=0&&right<=n-1)
            {
                if(s[left]==s[right])
                {
                    if(right-left+1>len1)
                    {
                        len1=right-left+1;
                        begin=left;
                    }
                    left--;
                    right++;
                }
                else
                break;
            }
            left=i,right=i+1;
            while(left>=0&&right<=n-1)
            {
                if(s[left]==s[right])
                {
                    if(right-left+1>len1)
                    {
                        len1=right-left+1;
                        begin=left;
                    }
                    left--;
                    right++;
                }
                else
                break;
            }
        }
        return s.substr(begin,len1);
    }
};

3.二进制求和

67. 二进制求和 - 力扣(LeetCode)

这题和链表中的一道题"两数相加"逻辑基本一致,不再赘述,只有一个小细节要提一下:因为相加是从最低位开始相加,所以最终结果的最低位先放入string,故最后要把string逆序一下,可以自己写函数,也可以用reverse(ret.begin(),ret.end());

代码如下:

cpp 复制代码
class Solution {
public:
    string addBinary(string a, string b) 
    {
        int cur1=a.size()-1,cur2=b.size()-1;
        int t=0;
        string ret;
        while(t||cur1>=0||cur2>=0)
        {
            if(cur1>=0)
            {
                t+=a[cur1]-'0';
                cur1--;
            }
            if(cur2>=0)
            {
                t+=b[cur2]-'0';
                cur2--;
            }
            int tmp=t%2+'0';
            ret+=tmp;
            t/=2;
        }
        for(int i=0;i<=(ret.size()-1)/2;i++)
        {
            swap(ret[i],ret[ret.size()-1-i]);
        }
        return ret;
    }
};

4.字符串相乘

43. 字符串相乘 - 力扣(LeetCode)

①竖式相乘模拟(不建议,代码复杂)

再两两相加tmp中的每一组数,最后把得到的字符串逆序,注意如果num1或num2为'0'不处理的话,直接相乘可能会得到多个0,所以对于这种情况要在函数开头处理一下。

②不进位相乘,最后整体处理

由于储存单位相乘的结果不能用字符串,故用数组tmp,分析可得,数组的长度应为n1+n2-1

num1和num2都要逆序,若num1和num2都逆序了,那么单位相乘的结果刚好可以放在tmpi+j的位置,且是+=,最后将处理后的字符逆序即可

代码如下:

cpp 复制代码
class Solution {
public:
    string multiply(string num1, string num2) 
    {
        if(num2=="0"||num1=="0")
        {
            return "0";
        }
        int n1=num1.size();
        int n2=num2.size();
        vector<int> tmp(n2+n1-1);
        reverse(num1.begin(),num1.end());
        reverse(num2.begin(),num2.end());
        for(int i=0;i<n2;i++)
        {
            for(int j=0;j<n1;j++)
            {
                tmp[i+j]+=(num1[j]-'0')*(num2[i]-'0');
            }
        }
        int t=0;
        int cur=0;
        string ret;
        while(t||cur<tmp.size())
        {
            if(cur<tmp.size())
            {
                t+=tmp[cur++];
            }
            ret+=t%10+'0';
            t/=10;
        }
        reverse(ret.begin(),ret.end());
        return ret;
    }
};

第二种算法的时间复杂度比方法一的好很多,且代码较好写。

相关推荐
倒头就睡的小比特4 天前
算法竞赛C++常用的STL
c++·算法
weilx12344 天前
C++笔记-文件IO-<fcntl.h>
c++
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读4 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
猎头南楼4 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
Smileyqp沛沛4 天前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车4 天前
C/C++ 为什么需要编译器?
开发语言·c++
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark4 天前
大规模并行计算中的负载均衡算法研究4
算法
吞下星星的少年·-·4 天前
C++ 萌新语法入门篇
c++·算法比赛