1. 验证回文串
题目描述:如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。字母和数字都属于字母数字字符。给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。
示例 1:
输入: s = “A man, a plan, a canal: Panama”
输出:true
解释:“amanaplanacanalpanama” 是回文串。
示例 2:
输入:s = “race a car”
输出:false
解释:“raceacar” 不是回文串。
示例 3:
输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 “” 。
由于空字符串正着反着读都一样,所以是回文串。
提示:
1 <= s.length <= 2 * 105
s 仅由可打印的 ASCII 字符组成
题目链接:link
答:解题思路:由于判断回文时不区分字母大小写且忽略数字和字母字符以外的字符,所以需要先把字符串中的字符统一转成大写或小写。首先创建一个string类的tmp对象,遍历一遍字符串把数字和字母字符存储到tmp中,同时统一转换大小写,然后对tmp对象判断是否回文。
代码如下:
class Solution {
public:
bool isPalindrome(string s) {
// 所需变量
string tmp; // 存储原顺序的数字和字母字符
// 遍历字符串,存储数字和字母字符,同时把字母字符转换为小写
int len = s.size();
for (int i = 0; i < len; ++i)
{
if (isalnum(s[i])) // 头文件cctype中的函数,判断是否为数字和字母字符
{
// 如果是字母字符则转换为小写
if (isalpha(s[i]))
s[i] = tolower(s[i]);
// 存储
tmp += s[i];
}
}
// 遍历tmp字符串,判断是否回文
int begin = 0;
int end = tmp.size() - 1;
while (begin < end)
{
// 本组字符判断
if (tmp[begin] != tmp[end])
return false;
// 下一组
++begin;
--end;
}
return true;
}
};
2. 字符串相乘
题目描述:给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
示例 1:
输入: num1 = “2”, num2 = “3”
输出: “6”
示例 2:
输入: num1 = “123”, num2 = “456”
输出: “56088”
提示:
1 <= num1.length, num2.length <= 200
num1 和 num2 只能由数字组成。
num1 和 num2 都不包含任何前导零,除了数字0本身。
题目链接:link
答:解题思路:这道题也算C++ 习题精选(1)中字符串相加的进阶题了。字符串相加我们想到了数值相加,那么字符串相乘我们也可以想到数值相乘。首先,判断乘数是否为0,即判断两个字符串中是否有一个为0。然后用第二个字符串中的每一位去乘以第一个字符串,对每次相乘的结果补0,个位不补,十位补一个0。然后把这些相乘的结果加起来。
代码如下:
// 一次相乘的函数
static void once(const string& s, string& tmp, char c, int z)
{
// 如果乘数位0,直接返回
if (c == '0')
return;
int add = 0; // 进位值
int i = s.size() - 1;
int n;
int x = c - '0';
while (i >= 0 || add > 0)
{
// 每位的数字
n = i >= 0 ? s[i] - '0' : 0;
// 相乘
int reslut = n * x + add;
// 存储
add = (reslut / 10);
tmp += (reslut % 10 + '0');
// 下一位数字
--i;
}
// 反转字符串
reverse(tmp.begin(), tmp.end());
// 补0
while (z--)
tmp += '0';
}
// 两个字符串相加
static string add(const string& s1, const string& s2)
{
int i = s1.size() - 1, j = s2.size() - 1; // 每位的下标
int n1, n2; // 每位数
int add = 0; // 进位值
string tmp; // 存储相加结果
while (i >= 0 || j >= 0 || add > 0)
{
// 每位数的值
n1 = i >= 0 ? s1[i] - '0' : 0;
n2 = j >= 0 ? s2[j] - '0' : 0;
// 相加
int result = n1 + n2 + add;
// 存储
add = result / 10;
tmp += (result % 10 + '0');
// 下一组
--i;
--j;
}
// 反转字符串
reverse(tmp.begin(), tmp.end());
// 返回结果
return tmp;
}
class Solution {
public:
string multiply(string num1, string num2) {
// 如果有一个乘数为0,则返回0
if (num1 == "0" || num2 == "0")
return "0";
// 所需变量
string result; // 存储结果
// 用num2的每一位乘以num1,然后相加
int j = 0; // 补0的个数
for (int i = num2.size() - 1; i >= 0; --i, ++j)
{
// 存储每次相乘的结果
string tmp;
// 相乘
once(num1, tmp, num2[i], j);
// 相加每次结果并存储
result = add(result, tmp);
}
// 返回结果
return result;
}
};