基础算法:字符串系列

目录

一、最长公共前缀

二、最长回文子串

三、二进制求和

四、字符串相乘


一、最长公共前缀

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

解法一:两两比较

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        int n=strs.size();
        string ret=strs[0];
        for(int i=1;i<n;++i)
        {
            int cur=0;
            while(cur<=strs[i-1].size()&&cur<=strs[i].size())
            {
                if(ret[cur]==strs[i][cur])
                {
                    ++cur;
                }
                else 
                {
                    ret=ret.substr(0,cur);
                    break;
                }
            }
        }
        return ret;
    }
};

解法二:统一比较

问题在于如何 统一,嵌套for循环就行,外界变量绑定第几个元素,内的变量绑定行数

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        int n=strs.size(),cur=0;
        for(int i=0;i<strs[0].size();++i)
        {
            for(int j=1;j<strs.size();++j)
            {
                if(i>strs[j].size()||strs[0][i]!=strs[j][i])
                {
                    //如果不符合了,cur存的是上一次符合的末尾,直接return
                    return strs[0].substr(0,cur);
                }
            }
            //所有的字符串都遍历完了,代表cur位置符合,++cur
            ++cur;
        }
        return strs[0];
    }
};

二、最长回文子串

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

解法一:中心扩展算法

基于回文特性,使用中心扩展算法,即先固定一个中心,再开始往左右找

注意substr参数,s.substr(起始下标,长度)

我说之前做到这题怎么脑海里总有种思路是从后往前遍历,然后在遍历的位置往左右拓展,这就复习到了,真好,感觉这种思路也相当于是一种暴力吧

class Solution {
public:
    string longestPalindrome(string s) {
        int begin=0,len=0,left,right;
        for(int i=0;i<s.size();++i)
        {
            //奇数长度子串
            left=right=i;
            while(left>=0&&right<=s.size()-1&&s[left]==s[right])
            {
                --left;
                ++right;
            }
            if(right-left-1>len)
            {
                begin=left+1;
                len=right-left-1;
            }
            //偶数长度子串
            left=i,right=i+1;
            while(left>=0&&right<=s.size()-1&&s[left]==s[right])
            {
                --left;
                ++right;
            }
            if(right-left-1>len)
            {
                begin=left+1;
                len=right-left-1;
            }
        }
        return s.substr(begin,len);
    }
};

解法二:dp

在dp:回文串系列中详细介绍了dp解决回文串问题的解法总结,感兴趣的可以点点主页到专栏看看。附链接:动规:回文串问题-优快云博客

dp[i][j]表示i~j闭区间,是否是回文串,判断是不是就从两端不断往内,

如果s[i]==s[j],如果i==j,返回true,如果i恰好是j左边一个数也就是i+1==j返回true

其他情况就要看dp[i+1][j-1],因为需要后边的数据,所以i层需要倒着填。

class Solution {
public:
    string longestPalindrome(string s) {
        int n=s.size(),len=0,begin=0;
        vector<vector<bool>> dp(n,vector<bool>(n));
        for(int i=n-1;i>=0;--i)
        {
            for(int j=i;j<n;++j)
            {
                if(s[i]==s[j])dp[i][j]=i+1<j?dp[i+1][j-1]:true;
                if(dp[i][j]&&len<j-i+1)
                {
                    len=j-i+1;begin=i;
                }
            }
        }
        return s.substr(begin,len);
    }
};

三、二进制求和

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

模拟加法,逢二进一,无需多言。

注意是字符形式,所以取数要-'0',ret+=num+'0',这一块很容易出错

相信聪明的你一定很快就会写出来了♪(^∇^*)

class Solution {
public:
    string addBinary(string a, string b) {
        //从最低位开始
        int cur1=a.size()-1,cur2=b.size()-1,t=0;
        string ret;
        while(cur1>=0||cur2>=0||t)
        {
            if(cur1>=0)t+=a[cur1--]-'0';
            if(cur2>=0)t+=b[cur2--]-'0';
            ret+=t%2+'0';
            t/=2;
        }
        reverse(ret.begin(),ret.end());
        return ret;
    }
};

四、字符串相乘

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

高精度乘法,没什么好说的。

解法一:模拟竖式乘法

class Solution {
public:
    string multiply(string num1, string num2) {
        if(num1=="0"||num2=="0")
        {
            return "0";
        }
        int m=num1.size(),n=num2.size();
        vector<int>ans(m+n,0);
        for(int i=m-1;i>=0;--i)
        {
            for(int j=n-1;j>=0;--j)
            {
                //i,j位存在结果数组的i+j+1位
                int mul=(num1[i]-'0')*(num2[j]-'0');
                int sum=mul+ans[i+j+1];
                ans[i+j+1]=sum%10;
                //处理进位
                ans[i+j]+=sum/10;
            }
        }
        
        string ret;
        for(int num:ans)
        {
            //处理前导零
            if(!(ret.empty()&&num==0))
            {
                ret+=num+'0';
            }
        }
        return ret;
    }
};

优化解法一,最后再处理进位

class Solution {
public:
    string multiply(string num1, string num2) {
        int m=num1.size(),n=num2.size();
        //因为先不考虑进位,所以我们只需要开m+n-1大小即可
        vector<int> arr(m+n-1);
        for(int i=m-1;i>=0;--i)
        {
            for(int j=n-1;j>=0;--j)
            {
                //i,j位置映射到i+j位置
                arr[i+j]+=(num1[i]-'0')*(num2[j]-'0');
            }
        }
        string ret;
        int cur=m+n-2,t=0;
        while(cur>=0||t)
        {
            if(cur>=0)t+=arr[cur--];
            ret+=t%10+'0';
            t/=10;
        }
        while(ret.size()>1&&ret.back()=='0')ret.pop_back();
        reverse(ret.begin(),ret.end());
        return ret;
    }
};

此篇完。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_dindong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值