字符串相加
题目来源
力扣(LeetCode): 字符串相乘
题目描述
给定两个以字符串形式表示的非负整数 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本身。
思路分析
- 排除有’0’的情况
- 定义一个字符串保存乘积结果,这个串的长度是两个乘数长度之和
- 两层循环,从低位到高位开始相乘,这里必须将两个数全部转换为int类型相乘,定义临时变量保存乘积
- ▲用k表示当前乘积要保存在的位置,如果有进位则将进位结果保存在k-1的位置,由于char类型范围较小,所以乘积不能直接与ret当前位置的值相加,否则有可能超出char类型取值范围,如:得到乘积81若与’0’相加超出char类型范围。正确的处理方式:先将乘积结果进位保留个位与ret当前位相加,并再次处理加和的进位
- 结果放入字符串中时要转换成char类型,因为字符串每个位置都被初始化为了’0’,所以只需要将乘积加到对应位置即可
- 得到结果后,去除最高位的’0’
代码展示
class Solution {
public:
string multiply(string num1, string num2) {
//有一个乘数为0则积为0
if (num1 == "0" || num2 == "0")
{
return "0";
}
//找较长的串作左操作数(个人习惯,这步可以省略)
if (num1.size() < num2.size())
{
num1.swap(num2);
}
int LeftSize = num1.size();
int RightSize = num2.size();
//保存乘积的字符串,两个数乘积最大位数为两个数位数之和
int RetSize = LeftSize + RightSize;
string ret(RetSize, '0');
int m = 1;//m标记保存结果数据的起始位
for (int i = RightSize - 1; i >= 0; i--)
{
int k = RetSize - m;
for (int j = LeftSize - 1; j >= 0; j--)
{
//定义临时变量保存乘积,int类型
int temp = (num2[i] - '0') * (num1[j] - '0');
//进位,因为乘积最大位81,加上'0'会超出char类型范围,所以要分两次处理进位
ret[k - 1] += temp / 10;
temp %= 10;
ret[k] += temp;
//临时变量temp加到ret字符串中后还要再次处理进位
while (ret[k] > '9')
{
ret[k] -= 10;
ret[k - 1] += 1;
}
k--;//ret中保存结果的位置左移
}
m++;//ret中保存结果的起始位置左移一位
}
//去除最高位的'0'
int count = 0;
for (auto ch : ret)
{
if (ch != '0')
{
break;
}
count++;
}
ret.erase(0, count);
return ret;
}
};
总结
难点及易错点:
- 忽略有’0’的情况
- 两次处理进位结果
- 对于int类型,可以用“除10”和“模10”处理进位
- 保存结果的字符串位置的偏移,内层循环每次结束左移一位,外层循环每轮结束将起始位置左移一位
- 去除结果最高位的’0’