【优选算法】字符串

目录

一、最长公共前缀

题目描述:

思路讲解:

本题需要找到所有字符串的公共前缀,那么我们可以先找到两个字符串的公共前缀,再跟其他字符串得到新的公共前缀,重复这个操作,最终找到所有字符串的公共前缀。

除了比较两个字符串的方式,还可以同时比较所有字符串,我们可以先找到最短字符串并记录它的长度,我们使用这个长度用来遍历所有字符串,就不会出现越界的情况,每遍历1位,就判断当前位上所有字符串上的字符是否相同,相同则向后遍历,不相同或是遍历完后则返回前面部分。

编写代码:

cpp 复制代码
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        string ans;
        int strsLen = strs.size();
        int MinStrLen = 201;   // 记录最短

        for(int i = 0 ; i < strsLen ;i++)
        {
            int strLen = strs[i].size();
            MinStrLen = MinStrLen <  strLen ? MinStrLen : strLen;
        }

        for(int i = 0 ; i < MinStrLen ;i++)
        {
            char ch = strs[0][i];
            for(int j = 0 ; j < strsLen ; j++)
            {
                if(ch != strs[j][i])
                    return ans;
            }
            ans += ch;
        }

        return ans;
    }
};

二、最长回文子串

题目描述:

思路讲解:

本题的暴力解法是找出字符串的所有子字符串,判断这些子字符串中有哪些字符串是符合回文规则的,并找到最长的一条返回,按照这个思路来讲,本题的时间复杂度将会达到O(n3),并不是一个很好的解法。

本题我们使用中心扩展算法来解决本题,首先定义一个中心点在数组的最左边,在定义两个变量来记录回文字符串的左右边界的下标,然后从中心点向两边延展,若两个位置的字符相同则继续向两边延展,当两个位置的字符不相同或是其中一边越界,与目前最长的回文字符串作比较,大于则更新新回文字符串的左右边界的下标,小于等于则不做处理,再将中心点向右移动,再重复上面的操作。

上面的操作只针对了回文字符串为奇数的情况,若为偶数的情况,则选最左边两个相邻的两个点作为中心点,然后从中心点向两边延展,重复上面的操作。

编写代码:

cpp 复制代码
class Solution {
public:
    string longestPalindrome(string s) {
        int sLen = s.size();
        int MaxLeft = 0 , MaxRight = 0;
        for(int i = 0 ; i < sLen ; i++)
        {
            // 回文为奇数个的情况
            int left = i , right = i;

            // 当两个字母相同向两边延伸
            while((left >= 0 && right < sLen) && s[left] == s[right])
            {
                left--;
                right++;
            }
            // 不相同时,判断与之前最长回文串的长度作比较
            if(right - left - 2> MaxRight - MaxLeft)
            {
                MaxLeft = left + 1;
                MaxRight = right - 1;
            }

            // 回文为偶数个的情况
            left = i , right = i + 1;
            // 当两个字母相同向两边延伸
            while(left >= 0 && right < sLen && s[left] == s[right])
            {
                left--;
                right++;
            }
            // 不相同或越界时,判断与之前最长回文串的长度作比较
            if(right - left - 2 > MaxRight - MaxLeft)
            {
                MaxLeft = left + 1;
                MaxRight = right - 1;
            }
        }
        return s.substr(MaxLeft , MaxRight - MaxLeft + 1);
    }
};

三、二进制求和

题目描述:

思路讲解:

本题的思路是将两个字符串逆转,然后将两个字符串就从低位开始相加,得到的字符串反转后得到答案。

编写代码:

cpp 复制代码
class Solution {
public:
    string addBinary(string a, string b) {
        reverse(a.begin(),a.end());
        reverse(b.begin(),b.end());
        string ans;

        int aLen = a.size() , bLen = b.size();
        int add = 0;  // 代表进位
        
        for(int i = 0 ; i < aLen || i < bLen || add; i++)
        {
            int num1 = i < aLen ? a[i] - '0' : 0;
            int num2 = i < bLen ? b[i] - '0' : 0;

            int sum = num1 + num2 + add;
            add = sum / 2;
            ans += (sum % 2) + '0';
        }
        reverse(ans.begin(),ans.end());
        return ans;
    }
};

四、字符串相乘

题目描述:

思路讲解:
解法一:"模拟"列竖式运算

将num1和num2逆转,定义一个字符串str来记录答案,定义一个字符串tmp记录num2中每一个数字乘num1得到的字符串,并将tmp与str相加,当得到的所有tmp都相加以后,需要注意的是这里我们将num1和num2逆转以后再计算的,所以这里的str是逆序的,所以再将str逆转就可以得到答案。

使用这个方法有三个细节点:

  1. 高位相乘时,需要补上"0"
  2. 处理前导0,当两个字符串中有一个位0就返回0
  3. 需要将得str逆转得到答案

解法二 :无进位相乘然后相加,最后处理进位

将num1和num2逆转,定义两个变量n,m分别记录num1和num2的长度,那么num1和num2相乘得到结果的长度必定为n+m-1,定义一个数组int tmp[n+m-1]记录结果中每一个位置的无进位相乘的结果,将num1中的每一位与num2中的每一位相乘,得到的结果放入到tmp中,放入tmp中位置的计算公式为num1当前数字下标与num2当前数字下标相加,当相乘完后,再处理数组tmp的进位,定义一个字符串ans来记录处理tmp得到的结果,需要注意的是这里我们将num1和num2逆转以后再计算的,所以这里的ans是逆序的,我们需要逆转ans才能得到最终的答案。

使用这个方法有三个细节点:

  1. 计算相乘时,加入到tmp位置的计算方式
  2. 处理前导0,当两个字符串中有一个位0就返回0
  3. 需要将得ans逆转得到答案

编写代码:

cpp 复制代码
class Solution {
public:
    string multiply(string num1, string num2) {
        int numLen1 = num1.size();
        int numLen2 = num2.size();

        if((numLen1 == 1 && num1[0] == '0') || numLen2 == 1 && num2[0] == '0' )
            return "0";

        reverse(num1.begin(),num1.end());
        reverse(num2.begin(),num2.end());
        
        vector<int> v(numLen1 + numLen2 - 1);

        for(int i = 0 ; i < numLen1 ; i++)
        {
            for(int j = 0 ; j < numLen2 ; j++)
            {
                v[i+j] += (num1[i] - '0') * (num2[j] - '0');
            }
        }

        int add = 0;
        string ans;
        for(int i = 0 ; i < v.size() ; i++)
        {
            int sum = v[i] + add;
            add = sum / 10;
            ans += to_string(sum % 10);
        }

        while(add)
        {
            ans += to_string(add % 10);
            add /= 10;
        }

        reverse(ans.begin(),ans.end());
        return ans;
    }
};

结尾

如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。

希望大家以后也能和我一起进步!!🌹🌹

如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹

相关推荐
daily_233315 分钟前
coding ability 展开第九幕(位运算——进阶篇)超详细!!!!
算法·位运算
柏木乃一19 分钟前
双向链表增删改查的模拟实现
开发语言·数据结构·算法·链表
whltaoin2 小时前
Java实现N皇后问题的双路径探索:递归回溯与迭代回溯算法详解
java·算法
同勉共进3 小时前
虚函数表里有什么?(二)——普通单继承下的虚函数表
c++·单继承·虚函数表·dynamic_cast·rtii
梭七y4 小时前
【力扣hot100题】(032)排序链表
算法·leetcode·链表
SsummerC4 小时前
【leetcode100】数组中的第K个最大元素
python·算法·leetcode
编程绿豆侠4 小时前
力扣HOT100之链表:206. 反转链表
算法·leetcode·链表
永恒迷星.by5 小时前
文件操作(c语言)
c语言·c++·算法·文件操作
还有你Y5 小时前
MIMO预编码与检测算法的对比
算法·预编码算法
凯强同学6 小时前
第十四届蓝桥杯大赛软件赛省赛Python 大学 C 组:7.翻转
python·算法·蓝桥杯