📝前言说明:
- 本专栏主要记录本人的基础算法学习以及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 解决 FloodFill | BFS 解决最短路径 |
| 多源 BFS | BFS 解决拓扑排序 |
题单汇总链接:点击 → 题单汇总
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(k2∗max(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(m∗n)
空间复杂度:
O
(
m
+
n
)
O(m+n)
O(m+n)
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

1181





