字符串

1.最长公共前缀

在这里插入图片描述

法一:两两比较。先比较两个字符串,得到它们的最长公共前缀,再拿这个最长公共前缀与下一个字符串比较,得到新的最长公共前缀。

法二:统一比较。以第一个字符串为基准,比较所有字符串的 i 位置的字符是否一致,如果不一致或 i 越界,则返回strs[0].substr(0,i)。
在这里插入图片描述

//法一:两两比较
class Solution {
public:
    string FindCommon(string& s1, string& s2)
    {
        int i = 0;
        while (i < min(s1.size(), s2.size()) && s1[i] == s2[i])
            i++;
        return s1.substr(0, i);
    }
    string longestCommonPrefix(vector<string>& strs)
    {
        string ret = strs[0];
        for (int i = 1;i < strs.size();i++)
            ret = FindCommon(ret, strs[i]);
        return ret;
    }
};

//法二:统一比较
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs)
    {
        for (int i = 0;i < strs[0].size();i++)
        {
            char c = strs[0][i];
            for (int j = 1;j < strs.size();j++)
                if (i == strs[j].size() || c != strs[j][i])
                    return strs[0].substr(0, i);
        }
        return strs[0];
    }
};

2.最长回文子串

在这里插入图片描述

求回文字符串,可以用中心扩展算法。从某个字符s[i]开始,left、right指针同时向左右两侧移动,当指针未越界且s[left]==s[right]时,left–,right++,两指针停止移动时,两指针之间的区域为回文子串。记录起点pos=left+1,回文子串长度len=right-left-1。left和right同时从 i 位置开始,只能得到奇数长度的字符串,所以当遍历完 i 为中心的奇数长度回文子串后,令left=i,right=i+1,继续遍历 i 为中心的偶数长度回文子串。

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

3.二进制求和

在这里插入图片描述

这类题属于高精度运算,一般是高精度加法、高精度乘法等。解决此类题只需模拟竖式计算即可。

class Solution {
public:
    string addBinary(string a, string b)
    {
        string ret;
        int cur1 = a.size() - 1, cur2 = b.size() - 1, t = 0;

        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;
    }
};

4.字符串相乘

在这里插入图片描述

法一:模拟竖式计算。与上题类似,需要注意高位相乘时要补0,其中一个乘数为0时结果直接为0,注意最后字符串要逆序。

法二:无进位相乘。在法一的基础上优化,使用无进位相乘,最后处理进位。无进位相乘如下图所示。

在这里插入图片描述

字符串先逆置,创建整型数组tmp记录无进位相乘的结果,可以发现规律,tmp的长度为num1.size()+num2.size()-1,每次无进位相乘的结果放在tmp[i+j],i用来遍历num1,j用来遍历num2。当一个乘数为0时,如123*0,会得到000,此时要处理前导0。由于最终求得的ret是逆序的,此时ret的最后一个元素为最高位,如果最高位为0且ret长度大于1,则说明要处理前导0。

//无进位相乘
class Solution {
public:
    string multiply(string num1, string num2)
    {
        int n1 = num1.size(), n2 = num2.size();
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());
        vector<int> tmp(n1 + n2 - 1);
		
        //无进位相乘后相加
        for (int i = 0;i < n1;i++)
            for (int j = 0;j < n2;j++)
                tmp[i + j] += (num1[i] - '0') * (num2[j] - '0');
		
        //处理进位
        int cur = 0, t = 0;
        string ret;
        while (cur < n1 + n2 - 1 || t)
        {
            if (cur < n1 + n2 - 1)
                t += tmp[cur++];
            ret += t % 10 + '0';
            t /= 10;
        }

        while (ret.size() > 1 && ret.back() == '0')//处理前导0
            ret.pop_back();
        reverse(ret.begin(), ret.end());
        return ret;
    }
};

//直接模拟竖式计算
class Solution9 {
public:
    string AddString(string a, string b)//字符串相加
    {
        string ret;
        int cur1 = a.size() - 1, cur2 = b.size() - 1, t = 0;
        if (cur1 < 0)
            return b;
        if (cur2 < 0)
            return a;
        while (cur1 >= 0 || cur2 >= 0 || t)
        {
            if (cur1 >= 0)
                t += a[cur1--] - '0';
            if (cur2 >= 0)
                t += b[cur2--] - '0';
            ret += t % 10 + '0';
            t /= 10;
        }
        reverse(ret.begin(), ret.end());
        return ret;
    }
    
    string multiply(string num1, string num2)//字符串相乘
    {
        string ret;
        int cur1 = num1.size() - 1, cur2 = num2.size() - 1, t = 0;
        if (num1.size() == 1 && num1[cur1] == '0')
            return "0";
        if (num2.size() == 1 && num2[cur2] == '0')
            return "0";

        while (cur1 >= 0)
        {
            string tmp;
            while (cur2 >= 0 || t)
            {
                if (cur2 >= 0)
                    t += (num2[cur2--] - '0') * (num1[cur1] - '0');
                tmp += t % 10 + '0';
                t /= 10;
            }
            reverse(tmp.begin(), tmp.end());
            int n = num1.size() - 1 - cur1;
            while (n--)
                tmp += "0";
            ret = AddString(ret, tmp);
            cur1--;
            cur2 = num2.size() - 1;
        }
        return ret;
    }
};
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐