Given two numbers represented as strings, return multiplication of the numbers as a string. Note: The numbers can be arbitrarily large and are non-negative.
解题分析:
大数乘法,我们可以使用一个数组模拟乘法操作
这里有个陷阱,数组我们是采用char数组还是int数组,很自然的想到用string,也就是char数组,但是string会出错
我们假设有一位是9×9=81,然后81 + ‘0’ = 81 + 48 = 129 超出了 char的表示范围[-128, 127], 会出现截断
我们采用int数组就可以解决此问题
class Solution { public: string multiply(string num1, string num2) { if (num1.size() == 0 || num2.size() == 0) return ""; reverse(num1.begin(), num1.end()); reverse(num2.begin(), num2.end()); vector<int> result(num1.size() + num2.size(), 0); int count = 0; for (int i = 0; i < num1.size(); ++i) { for (int j = 0; j < num2.size(); ++j) { result.at(i+j) += (num1.at(i) - '0') * (num2.at(j) - '0'); } } for (int i = 0; i < result.size(); ++i) { int tmp = result.at(i) + count; result.at(i) = tmp % 10; count = tmp / 10; } int zeroPos = 0; for (zeroPos = result.size() - 1; zeroPos >= 0; --zeroPos) { if (result.at(zeroPos) != 0) break; } result.erase(result.begin() + zeroPos + 1, result.end()); reverse(result.begin(), result.end()); string res(result.size(), '0'); for (int i = 0; i < result.size(); ++i) { res.at(i) += result.at(i); } if (res == "") { return "0"; } else { return res; } } };
1. 我们首先开辟一个vector,长度为 两个字符串长度值和
两个数相乘,结果的位数之和一定 <= 两乘数的位数之和
2. 计算每位之和,先不管进位,一定要注意是累加
因为乘法都是从最低位开始操作的,如果直接从string的最末尾操作,下标计算就会异常繁琐而且非直观,故我们首先先反转两个乘数,直观操作
result.at(i+j) += (num1.at(i) - '0') * (num2.at(j) - '0');
3. 处理进位
result.at(i) = tmp % 10;
4. 舍弃vector末尾0,因为我们开辟的vector是 >= 正确的结果值位数的,所以可能存在 末尾无用的0
例如 12 × 2 = 24 vector里面存储的是 result[0] = 4 result[1] = 2, result[2] = 0
所以我们要从末尾开始查找,去除末尾连续的0,找到第一个非0值下标,然后erase
为什么要从末尾向前查找呢? 因为会出现 12004这样的情况
5. 最后 如果 string为空,则返回"0" 这是因为 "0" * "0" = "00" 然后我们查找第一个非0,然后erase,这样string就为空了
既然如下总结所示,无用的进位0只可能出现在最高位,对应于result的最末位,那么我们可不可以直接erase最末一位就可以呢?
不可以,因为可能是 "9899" * "0" = "00000" 我们erase最末一位仍然格式不正确
所以必须从末尾向前开始查找第一个非0元素,然后erase其位置以后所有的0,当然这会出现 将"00000"全部擦除, 这是我们单独返回“0”
总结:
大数乘法:res.size()只可能为 num1.size() + num2.size() - 1 和 num1.size() + num2.size() 这两种情况,
并且无用的前置进位0只可能出现最高位num1.size() + num2.size()位置上
大数加法:res.size()只可能为 std::max(num1.size(), num2.size()) 和 std::max(num1.size(), num2.size()) + 1 这两种情况,
并且无用的前置进位0只可能出现最高位std::max(num1.size(), num2.size()) + 1位置上