【优选算法之字符串】No.12--- 经典字符串算法


前言

在这里插入图片描述

👧个人主页:@小沈YO.
😚小编介绍:欢迎来到我的乱七八糟小星球🌝
📋专栏:优选算法
🔑本章内容:字符串
记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~


一、字符串示例

1.1 最⻓公共前缀

  1. 题⽬链接:14. 最⻓公共前缀

  2. 题⽬描述:
    在这里插入图片描述

  3. 解法:
    算法思路:
    解法⼀(两两⽐较):
    我们可以先找出前两个的最⻓公共前缀,然后拿这个最⻓公共前缀依次与后⾯的字符串⽐较,这样就可以找出所有字符串的最⻓公共前缀。
    解法⼆(统⼀⽐较):
    题⽬要求多个字符串的公共前缀,我们可以逐位⽐较这些字符串,哪⼀位出现了不同,就在哪⼀位截⽌。

  4. C++代码

class Solution {
public:
    string maxCommonPrefix(string& s1,string& s2)
    {
        int minlen=s1.size()<s2.size()?s1.size():s2.size();
        string s;
        for(int i=0;i<minlen;i++)
        {
            if(s1[i]==s2[i])s+=s1[i];
            else break;
        }
        return s;
    }
    string longestCommonPrefix(vector<string>& strs) 
    {
        string s=strs[0];
        for(int i=1;i<strs.size();i++)
        {
            s=maxCommonPrefix(s,strs[i]);
        }
        return s;
    }
};
--------------------------------------------------------------------------------------------
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()||tmp!=strs[j][i])return strs[j].substr(0,i);
            }
        }
        return strs[0];
    }
};

1.2 最⻓回⽂⼦串

  1. 题⽬链接:5. 最⻓回⽂⼦串
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(中⼼扩散):
    算法思路:
    枚举每⼀个可能的⼦串⾮常费时,有没有⽐较简单⼀点的⽅法呢?
    对于⼀个⼦串⽽⾔,如果它是回⽂串,并且⻓度⼤于 2,那么将它⾸尾的两个字⺟去除之后,它仍然是个回⽂串。此这样去除,⼀直除到⻓度⼩于等于 2 时呢?⻓度为 1 的,⾃⾝与⾃⾝就构成回⽂;⽽⻓度为 2 的,就要判断这两个字符是否相等了。
    从这个性质可以反推出来,从回⽂串的中⼼开始,往左读和往右读也是⼀样的。那么,是否可以枚举回⽂串的中⼼呢?
    从中⼼向两边扩展,如果两边的字⺟相同,我们就可以继续扩展;如果不同,我们就停⽌扩展。这样只需要⼀层 for 循环,我们就可以完成先前两层 for 循环的⼯作量。
  4. C++代码
class Solution {
public:
    string longestPalindrome(string s) 
    {
        //固定一个下标
        int begin=0,len=0;
        int left=0,right=0;
        for(int i=0;i<s.size();i++)
        {
            left=i,right=i;
            //做一次奇数长度扩展
            while(left>=0&&right<s.size()&&s[left]==s[right])
            {
                left--;right++;
            }
            if(right-left-1>len)
            {
                len=right-left-1;
                begin=left+1;
            }
            //偶数长度扩展
            left=i,right=i+1;
            while(left>=0&&right<s.size()&&s[left]==s[right])
            {
                left--;right++;
            }
            if(right-left-1>len)
            {
                len=right-left-1;
                begin=left+1;
            }
        }
        return s.substr(begin,len);
    }
};

1.3 ⼆进制求和

  1. 题⽬链接:67. ⼆进制求和
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(模拟⼗进制的⼤数相加的过程):
    算法思路:
    模拟⼗进制中我们列竖式计算两个数之和的过程。但是这⾥是⼆进制的求和,我们不是逢⼗进⼀,⽽是逢⼆进⼀。
  4. C++代码
class Solution {
public:
    string addBinary(string a, string b) 
    {
       string ret;
       int n=a.size()-1,m=b.size()-1;
       int sum=0;
       while(n>=0||m>=0||sum)
       {
            if(n>=0)sum+=a[n--]-'0';
            if(m>=0)sum+=b[m--]-'0';
            ret+=to_string(sum%2);
            sum/=2;
       }
       reverse(ret.begin(),ret.end());
       return ret;
    }
};

1.4 字符串相乘

  1. 题⽬链接:43. 字符串相乘
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(⽆进位相乘然后相加,最后处理进位):
    算法思路:
    整体思路就是模拟我们⼩学列竖式计算两个数相乘的过程。但是为了我们书写代码的⽅便性,我们选择⼀种优化版本的,就是在计算两数相乘的时候,先不考虑进位,等到所有结果计算完毕之后,再去考虑进位。如下图:
    在这里插入图片描述
  4. C++代码
class Solution {
public:
    string multiply(string num1, string num2) 
    {
        //无进位相乘再相加
        int n=num1.size(),m=num2.size();
        vector<int> v(n+m-1);
        reverse(num1.begin(),num1.end());
        reverse(num2.begin(),num2.end());
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                int tmp=(num1[j]-'0')*(num2[i]-'0');
                v[i+j]+=tmp;
            }
        }
        int tmp=0,t=0;
        string s;
        while(tmp<n+m-1||t)
        {
            if(tmp<n+m-1)t+=v[tmp++];
            s+=(t%10)+'0';
            t/=10;
        }
        while(s.size()>1&&s.back()=='0')
            s.pop_back();
        reverse(s.begin(),s.end());
        return s;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小沈YO.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值