【专题十一】字符串

📝前言说明:

  • 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,按专题划分
  • 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
  • 文章中的理解仅为个人理解。如有错误,感谢纠错

🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础python入门基础C++学习笔记Linux
🎀优快云主页 愚润泽

你可以点击下方链接,进行该专题内不同子专题的学习

点击链接开始学习
双指针(1)双指针(2)
双指针(3)双指针(4)
滑动窗口(1)滑动窗口(2)
滑动窗口(3)滑动窗口(4)
二分查找(1)二分查找(2)
前缀和(1)前缀和(2)
前缀和(3)位运算(1)
位运算(2)模拟算法
快速排序归并排序
链表哈希表
字符串
队列 + 宽搜优先级队列
BFS 解决 FloodFillBFS 解决最短路径
多源 BFSBFS 解决拓扑排序

题单汇总链接:点击 → 题单汇总


14. 最长公共前缀

题目链接:https://leetcode.cn/problems/longest-common-prefix/description/
在这里插入图片描述

个人解

屎山代码:

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

时间复杂度: O ( S ) O(S) O(S),S 是所有字符串的字符总数
空间复杂度: O ( 1 ) O(1) O(1),不算ans


5. 最长回文子串

题目链接:https://leetcode.cn/problems/longest-palindromic-substring/description/
在这里插入图片描述

个人解

屎山代码(动态规划):

class Solution {
public:
    string longestPalindrome(string s) 
    {
        int n = s.size();
        vector<vector<bool>> dp(n, vector<bool>(n));
        // 填表
        string ans = "";
        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] && j - i + 1 > ans.size())
                    ans = s.substr(i, j - i + 1);
            }
        }
        return ans;
    }
};

时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( n 2 ) O(n^2) O(n2)


优质解

思路:

  • 中心扩展算法:借助回文串的特性来暴力枚举
  • 外层遍历:枚举中心点
  • 内层:用两个指针,从中心点开始往外扩展
    • 注意:奇数长度和偶数长度都要考虑
    • 奇数长度,左右指针从同一位置开始扩展
    • 偶数长度,先让左右指针相隔一个位置,再一起扩展

代码:

class Solution {
public:
    string longestPalindrome(string s) 
    {
        int n = s.size();
        int begin = 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)
            {
                begin = 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)
            {
                begin = left + 1;
                len = right - left - 1;
            }
        } 
        return s.substr(begin, len);
    }
};

时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( 1 ) O(1) O(1)


67. 二进制求和

题目链接:https://leetcode.cn/problems/add-binary/description/
在这里插入图片描述

个人解

思路:

  • 和之前相加两个链表的思路一样

屎山代码:

class Solution {
public:
    string addBinary(string a, string b) 
    {
        int i = a.size() - 1, j = b.size() - 1;
        int carry = 0;
        string ans = "";
        // 从末尾开始相加
        while(i >= 0 || j >= 0 || carry)
        {
            if(i >= 0)
                carry += a[i--] - '0'; // -- 去更高位
            if(j >= 0)
                carry += b[j--] - '0';
            ans = to_string(carry % 2) + ans;
            carry = carry / 2;
        }
        return ans;
    }
};

时间复杂度: O ( m a x ( m , n ) ) O(max(m,n)) O(max(m,n))
空间复杂度: O ( m a x ( m , n ) ) O(max(m,n)) O(max(m,n))


43. 字符串相乘(重点)

题目链接:https://leetcode.cn/problems/multiply-strings/description/
在这里插入图片描述

个人解

思路:

  • 利用大数相加:遍历一遍乘数,然后把当前位对应的被乘数进行多次累加

屎山代码:

class Solution {
public:
    // 大数相加
    string addBinary(string a, string b) 
    {
        int i = a.size() - 1, j = b.size() - 1;
        int carry = 0;
        string ans = "";
        // 从末尾开始相加
        while(i >= 0 || j >= 0 || carry)
        {
            if(i >= 0)
                carry += a[i--] - '0'; // -- 去更高位
            if(j >= 0)
                carry += b[j--] - '0';
            ans = to_string(carry % 10) + ans;
            carry = carry / 10;
        }
        return ans;
    }

    string multiply(string num1, string num2) 
    {
        if(num1 == "0" || num2 == "0") return "0";
        int n = num1.size();
        string ans = "0";
        // num1 当乘数
        for(int i = n - 1; i >= 0; i--)
        {
            string base = num2;
            base.append(n - 1 - i, '0');
            for(int j = 1; j <= num1[i] - '0'; j++)
                ans = addBinary(ans, base);
        }
        return ans;
    }
};

时间复杂度: O ( k 2 ∗ m a x ( m , n ) ) O(k^2*max(m,n)) O(k2max(m,n))


优质解

思路:

  • 列竖式计算(下图中数组下标画反了:应该是:0, 1, 2, 3, 4
  • 但是,为了书写代码的方便:在计算两数相乘的时候,先不考虑进位,等到所有结果计算完毕之后,再去考虑进位

在这里插入图片描述

代码:

class Solution {
public:
    string multiply(string num1, string num2) 
    {
        if(num1 == "0" || num2 == "0") return "0";
        int m = num1.size(), n = num2.size();
        // result 存储无进位相乘结果
        // 把 num1 当乘数,每位需要与num2 的n个数相乘
        vector<int> result2(m + n - 1, 0); // 无进位相乘后相加
        for(int i = 0; i < m; i++) // 遍历乘数
        {
            for(int j = 0; j < n; j++)
                result2[i + j] += (num1[i] - '0')* (num2[j] - '0');
        }
        string ans = "";
        int carry = 0, i = m + n - 2;
        while(i >= 0 || carry)
        {
            if(i >= 0)
            {
                carry += result2[i--];
            }
            ans = to_string(carry % 10) + ans;
            carry /= 10;
        }
        return ans;
    }
};

时间复杂度: O ( m ∗ n ) O(m*n) O(mn)
空间复杂度: O ( m + n ) O(m+n) O(m+n)


🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

愚润泽

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

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

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

打赏作者

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

抵扣说明:

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

余额充值