《最长公共前缀》
题目描述:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
示例 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、通过找到最子串的起始点,和长度就能比较得出谁是最长的子串。
《二进制求和》
题目描述:
给你两个二进制字符串 a
和 b
,以二进制字符串的形式返回它们的和。
示例 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类型的存储大小范围。
先拿这道题来看,具体的做法:
《字符串相乘》
题目描述:
给定两个以字符串形式表示的非负整数 num1
和 num2
,返回 num1
和 num2
的乘积,它们的乘积也表示为字符串形式。
**注意:**不能使用任何内置的 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元素,那这个位置就是答案的第一个元素下标