给定两个字符串,都有数字组成,求这两个字符串所表示的数字的乘积,返回字符串表示形式。两个字符串的长度 < 110. 除了数字0本身,没有前导0存在。
Input: num1 = "123", num2 = "456"
Output: "56088"
思路:
一、由于字符串表示的数很大,几十上百位,肯定不能将其转化为数字再乘积,运用小学数学思想,比如:12 * 34 ,先用 12 * 4 = 48 ,再用 12 * 3 = 36 ,但是因为3是十位上的,相加的时候要移位,所以,48中的8保留不变,用 4 + 36 = 40 ,最终得到408. 不断的重复上面的过程,最终得到答案。虽然能AC,但是时间复杂度很高。
class Solution { public: string multiply(string num1, string num2) { if (num1[0] == '0' || num2[0] == '0') return "0"; string res, product, carry; int n1 = num1.size(), n2 = num2.size(); for (int i = n1 - 1; i >= 0; i--) { int p1 = num1[i] - '0', tmp = 0, flag = 0;//进位的值 flag for (int j = n2 - 1; j >= 0; j--) { tmp = p1 * (num2[j] - '0') + flag; product = to_string(tmp % 10) + product; flag = tmp / 10; } if (flag > 0) product = to_string(flag) + product; //获得一个字符串的一位值对另一个字符串的所有数字乘积,保存为字符串 int res_len = res.size(), c = n1 - 1 - i;//移位个数 c carry = res; if (res_len > 0) { carry = res.substr(0, res_len - c); // 移位过后,需要相加的字符串 res = res.substr(res_len - c, c); //移位留下的字符串,保留不变 } res = twoStringSum(carry, product) + res; //两字符串相加得到的和,再接上移位留下的 product = ""; } return res; } string twoStringSum(string s1, string s2) { //两字符串相加 string res; int n1 = s1.size(), n2 = s2.size(), flag = 0; if (n1 == 0 || n2 == 0) return n1 == 0 ? s2 : s1; while (n1 || n2) { int x1 = n1 > 0 ? s1[n1-1] - '0' : 0; int x2 = n2 > 0 ? s2[n2-1] - '0' : 0; int sum = x1 + x2 + flag; res = to_string(sum % 10) + res; flag = sum / 10; n1 = n1 > 0 ? n1 - 1 : 0; n2 = n2 > 0 ? n2 - 1 : 0; } if (flag > 0) res = to_string(flag) + res; return res; } };
二、利用容器,空间换时间,参见Grandyang。
class Solution { public: string multiply(string num1, string num2) { string res = ""; int m = num1.size(), n = num2.size(); vector<int> vals(m + n); for (int i = m - 1; i >= 0; --i) { for (int j = n - 1; j >= 0; --j) { int mul = (num1[i] - '0') * (num2[j] - '0'); int p1 = i + j, p2 = i + j + 1, sum = mul + vals[p2]; vals[p1] += sum / 10; vals[p2] = sum % 10; } } for (int val : vals) { if (!res.empty() || val != 0) res.push_back(val + '0'); } return res.empty() ? "0" : res; } };