题目
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
分析
1、去年10月份的时候的做法,涉及到了很多string的加法运算,由于每次string相加,都会涉及内存的分配与拷贝,效率很差。因此这次用数组保存中间计算结果,最后再用stringstream拼接到一起,效率会提升很多。
2、这里引用LeetCode评论区一位朋友的图。可见,我们可以把每一位的计算结果保存在数组里,最后遍历一遍数组,该进位的进位,该相加的相加。
3、用来保存结果的数组大小设置为多少好呢。做一个简单的证明:
(1)有两个待相乘的字符串
A
A
A、
B
B
B
(2)令
C
=
1
0
B
.
l
e
n
g
t
h
(
)
C = 10^{B.length()}
C=10B.length(),有
C
.
l
e
n
g
t
h
(
)
=
B
.
l
e
n
g
t
h
(
)
+
1
C.length() = B.length() + 1
C.length()=B.length()+1
(3)则
(
A
∗
B
)
.
l
e
n
g
t
h
(
)
<
=
(
A
∗
C
)
.
l
e
n
g
t
h
(
)
=
A
.
l
e
n
g
t
h
(
)
+
B
.
l
e
n
g
t
h
(
)
(A * B).length() <= (A * C).length() = A.length() + B.length()
(A∗B).length()<=(A∗C).length()=A.length()+B.length()
所以数组取两个字符串的长度和就够用了。
代码
class Solution {
public:
int calStrMultiply(char c1, char c2) {
return (c1 - '0') * (c2 - '0');
}
void joinStr(string& str, const vector<int>& arr) {
stringstream ss;
int index = arr.size() - 1;
while (index > 0 && arr[index] == 0) {
--index;
}
for (int i = index; i >= 0; --i) {
ss << arr[i];
}
ss >> str;
}
string multiply(string num1, string num2) {
num1 = string(num1.rbegin(), num1.rend());
num2 = string(num2.rbegin(), num2.rend());
vector<int> aux(num1.size() + num2.size(), 0);
for (int i = num2.size() - 1; i >= 0; --i) {
for (int j = num1.size() - 1; j >= 0; --j) {
aux[i + j] += calStrMultiply(num1[j], num2[i]);
}
}
int carry = 0;
for (int i = 0; i < aux.size(); ++i) {
int curSum = carry + aux[i];
carry = curSum / 10;
aux[i] = curSum % 10;
}
string res = "";
joinStr(res, aux);
return res;
}
};