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都逆序了,那么单位相乘的结果刚好可以放在tmp[i+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;
    }
};

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

相关推荐
ht巷子1 小时前
Asio学习:定时器
c++·计算机网络
passxgx1 小时前
12.3 多维高斯分布与加权最小二乘法
线性代数·算法·最小二乘法
少许极端1 小时前
算法奇妙屋(三十)-递归、回溯与剪枝的综合问题 3
算法·深度优先·剪枝·数独·n皇后
陳10301 小时前
C++:哈希表
开发语言·c++·散列表
稻草猫.1 小时前
SpringBoot日志全解析:从调试到持久化
java·开发语言·spring boot·java-ee·idea
WBluuue2 小时前
数据结构与算法:01分数规划
c++·算法
小鸡吃米…2 小时前
Python线程同步
开发语言·数据结构·python
白帽子黑客-宝哥2 小时前
渗透测试“保姆级”实战成长手册
开发语言·网络安全·渗透测试·php
七七肆十九2 小时前
PTA 习题9-1 时间换算
c语言·算法