目录
题目描述
思路:
普通竖式
优化竖式
优化代码
一开始我想要使用atoi()和to_string()两个函数(分别来自cstdlib和sstream库),但是最后的结果超过了 long的限制.所以我就没法了,想着,硬着头皮模拟一遍好了.
思路比较简单,我们写两个函数.一个函数负责返回两个string相加的结果,另一个函数负责模拟每一行相乘的结果.先算出相乘的结果,再拿结果和之前算出的res进行字符串相加函数操作.中间有一些细节问题要注意:
1)每一次保存一行数据的ans字符串,这个字符串每一次要在头部加上有规律个数的字符'0'来模拟手动乘法中的移位计算.
2)我们在进行add(res,ans)之前.需要先将ans字符串进行reverse操作!
class Solution {
public:
string multiply(string num1, string num2) {
if (num1[0] == '0' || num2[0] == '0') return "0";
int i = num2.size() - 1;
int sub = num2.size() - 1;
int j = num1.size() - 1;
int temp_i;
int temp_j;
int mul = 0;
string ans = "";
string res = "";
for (; i >= 0; --i) {
temp_i = i;
temp_j = j;
ans.clear();
while (sub - temp_i > 0) {
ans.push_back('0');
temp_i++;
}
/*num1*num2[i],结果保存在ans中*/
while (mul > 0 || temp_j >= 0) {
int temp_mul = (num2[i] - '0') * (temp_j>=0?num1[temp_j] - '0':0) + mul;
ans.push_back(temp_mul % 10+'0');
mul = temp_mul / 10;
--temp_j;
}
/*再令res=addString(res,ans)*/
reverse(ans.begin(), ans.end());
res = addString(res, ans);
}
return res;
}
string addString(string nums1, string nums2) {
int i = nums1.size()-1,j=nums2.size()-1;
int add = 0;
string ans = "";
while (i >= 0 || j >= 0 || add > 0) {
int x = i >= 0 ?nums1[i]-'0' : 0;
int y = j >= 0 ?nums2[j]-'0' : 0;
int res = x + y + add;
ans.push_back(res % 10 + '0');
res /= 10;
add = res;
--i , --j;
}
reverse(ans.begin(), ans.end());
return ans;
}
};
这里就不做那些复制粘贴的恶心事二了.
直接发链接:https://leetcode-cn.com/problems/multiply-strings/solution/
中间想了一个问题很久:
我们在模拟res[i+j]的时候,为什么是res[i+j]+(之前res[i+j+1]+n1*n2)/10 ?????
个人理解把它当做一个递归式,当前的一定要取余10,但是对于[i+j]位,我们可以允许它暂时>=10,因为i+j位会被下一次的循环迭代取余掉,所以不用担心i+j位>=10,但是这里的i+j+1位一定要是刚才没有更新过的i+j+1位,不然会出现加了两次res[i+j+1]的错误情况!
class Solution {
//public: 普通竖式和优化竖式的区别在于说普通竖式会花很多时间在字符串相加这件事上
// string multiply(string num1, string num2) {
// if (num1[0] == '0' || num2[0] == '0') return "0";
// int i = num2.size() - 1;
// int sub = num2.size() - 1;
// int j = num1.size() - 1;
// int temp_i;
// int temp_j;
// int mul = 0;
// string ans = "";
// string res = "";
// for (; i >= 0; --i) {
// temp_i = i;
// temp_j = j;
// ans.clear();
// while (sub - temp_i > 0) {
// ans.push_back('0');
// temp_i++;
// }
// /*num1*num2[i],结果保存在ans中*/
// while (mul > 0 || temp_j >= 0) {
// int temp_mul = (num2[i] - '0') * (temp_j>=0?num1[temp_j] - '0':0) + mul;
// ans.push_back(temp_mul % 10+'0');
// mul = temp_mul / 10;
// --temp_j;
// }
// /*再令res=addString(res,ans)*/
// reverse(ans.begin(), ans.end());
// res = addString(res, ans);
// }
// return res;
// }
//
// string addString(string nums1, string nums2) {
// int i = nums1.size()-1,j=nums2.size()-1;
// int add = 0;
// string ans = "";
// while (i >= 0 || j >= 0 || add > 0) {
// int x = i >= 0 ?nums1[i]-'0' : 0;
// int y = j >= 0 ?nums2[j]-'0' : 0;
// int res = x + y + add;
// ans.push_back(res % 10 + '0');
// res /= 10;
// add = res;
// --i , --j;
// }
// reverse(ans.begin(), ans.end());
// return ans;
// }
public:
/*优化竖式则不会,优化竖式在直接依据位数关系得到数值*/
string multiply(string num1, string num2) {
if (num1[0] == '0' || num2[0] == '0') return "0";
int* res = new int[num1.size() + num2.size()];
memset(res, 0, sizeof(int) * (num1.size() + num2.size()));
for (int i = num1.size() - 1; i >= 0; --i) {
int n1 = num1[i] - '0';
for (int j = num2.size() - 1; j >= 0; --j) {
int n2 = num2[j] - '0';
int temp = n1 * n2+res[i+j+1];
res[i + j + 1] = (temp) % 10;
res[i + j] = res[i + j] + (temp) / 10;//这里肯定是要允许它>=10的,就像是递归,我们每一次只要考虑当前两个数.[i+j],[i+j+1] [i+j]就是当前位置的进位位,为n1*n2+原来[i+j+1]位的进位位
}
}
string res_s = "";
for (int i = 0; i < num1.size() + num2.size() ; ++i) {
if (i == 0 && res[0] == 0) continue;
res_s.push_back(res[i] + '0');
}
delete[]res;
return res_s;
}
};