算法分析 —— 《字符串》

《最长公共前缀》

题目描述:

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

示例 1:

输入:strs = ["flower","flow","flight"]
输出:"fl"

示例 2:

输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。

代码实现:

class Solution 
{
public:
    string longestCommonPrefix(vector<string>& strs) 
    {
        string ans;
        for(int i = 0; i < strs[0].size(); ++i)
        {
            for(int j = 1; j < strs.size(); ++j)
            {
                if(strs[j][i] != strs[0][i]) return ans;
            }
            ans += strs[0][i];
        } 
        return ans;
    }
};

代码解析:

《最长回文子串》

题目描述:

给你一个字符串 s,找到 s 中最长的 回文 子串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"

代码实现:

class Solution 
{
public:
    string longestPalindrome(string s) 
    {
        int begin = 0, len = 0;
        for(int i = 0; i < s.size(); ++i)
        {
            int left = i, right = i;
            while(left >= 0 && right < s.size() && 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() && s[left] == s[right])
            {
                --left;
                ++right;
            }
            if(right - left - 1 > len) 
            {
                begin = left + 1;
                len = right - left - 1;
            }
        }
        return s.substr(begin, len);
    }
};

代码解析:

先解释一下什么是回文串,回文串就是一个字符串,正着读和反着读都是一样的,所以对于像这种回文串是一某个字符串的子串的情况题型下,我可以采取中心扩展算法来解决。

具体的做法就是:

1、固定一个值

2、分别判断左边的值是否等于右边的值

3、等于的话,就各自往反方向走

因为回文串是一个子串,所以本质还得去遍历全局的字符串,那么这就会导致一种情况,我们需要考虑该如何确定左指针和右指针的起始位置,如果有这么两种情况:

因为你无法判断最长的回文子串是偶数的还是奇数的,因为可能最长子串是偶数而你只计算了奇数情况的,因此你每个点都要去考虑,而判断回文子串是偶数还是奇数的算法并不一样,关键还是在于left指针和right指针的初始位置不一致所导致,所以现在有:

1、确定每个点都要进行两次判断,一次奇数判断和偶数判断

2、两次判断指针的初始化状态都不一样

3、通过找到最子串的起始点,和长度就能比较得出谁是最长的子串。

《二进制求和》

题目描述:

给你两个二进制字符串 ab ,以二进制字符串的形式返回它们的和。

示例 1:

输入:a = "11", b = "1"
输出:"100"

示例 2:

输入:a = "1010", b = "1011"
输出:"10101"

代码实现:

class Solution 
{
public:
    string addBinary(string a, string b) 
    {
        string ans;
        int cur1 = a.size() - 1;
        int cur2 = b.size() - 1;
        int carry = 0;
        
        while(cur1 >= 0 || cur2 >= 0 || carry)
        {
            if(cur1 >= 0) carry += (a[cur1--] - '0');
            if(cur2 >= 0) carry += (b[cur2--] - '0');
            ans += (carry % 2) + '0';
            carry = carry / 2;
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};

代码解析:

二进制相加是我们在学习编程前期就必须掌握的技能,然而随着我们的技术不断进步,我们也需要着手通过代码解决二进制的相加问题,这道题还是很重要的,因为通过这道题我们可以对高精度的加减乘除法均有了解,而高精度运算算是一个算法入门技能,为什么是高精度呢,因为一定存在某些特别大的数之间进行运算,这里的大指的就是超过int类型甚至是long long类型的存储大小范围。

先拿这道题来看,具体的做法:

《字符串相乘》

题目描述:

给定两个以字符串形式表示的非负整数 num1num2,返回 num1num2 的乘积,它们的乘积也表示为字符串形式。

**注意:**不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

示例 1:

输入: num1 = "2", num2 = "3"
输出: "6"

示例 2:

输入: num1 = "123", num2 = "456"
输出: "56088"

代码实现:

class Solution 
{
public:
    string multiply(string num1, string num2) 
    {
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());

        vector<int> ans;
        ans.resize(num1.size() + num2.size() + 1);
        for(int i = 0; i < num1.size(); ++i)
        {
            for(int j = 0; j < num2.size(); ++j)
            {
                ans[i + j] += (num1[i] - '0') * (num2[j] - '0');
                if(ans[i + j] >= 10)
                {
                    ans[i + j + 1] += ans[i + j] / 10;
                    ans[i + j] = ans [i + j] % 10;
                }
            }
        }

        int index = ans.size() - 1;
        while(index >= 0)
        {
            if(ans[index] != 0) break;
            index--;
        }
        if(index < 0) return "0";

        string ret;
        while(index >= 0) ret += (ans[index--] + '0');
        return ret;
    }
};

代码解析:

像这种题目就是一个典型的高精度乘法,我们首先需要来了解一下惩罚底层是如何实现的:

在我们的正常解法中,我们是按照逆序的方式去进行运算的,因此我们可以预先将两个字符串逆置一遍,再进行运算,而这个时候如果我们给两个字符串的每个元素都看看他们的下标,我们就会发现一个有趣的规律:

ans[i + j] += (num1[i]) * (num2[j]);

要记住这里是加等,因为会有其他的下标组合会满足相同。

而当ans[i + j] 是一个两位数时,我们就需要进位,进位的方式也很简单,我们只需要在ans[i + j + 1] 加上 ans[i + j] / 10即可,同时还需要进行取模操作取出个位数。

最后最后,我们完成乘法操作后,我们用来存答案的数组里是会有答案的,但是其后面会存在很多个0,因为我们为了操作方便,会提前对数组进行初始化num1.size() + num2.size() 个0,因此我们还要从后往前走,找到第一个非0元素,那这个位置就是答案的第一个元素下标

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无双@

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

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

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

打赏作者

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

抵扣说明:

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

余额充值