共计 1442 个字符,预计需要花费 4 分钟才能阅读完成。
读完本文,你能够去力扣拿下如下题目:
43. 字符串相乘
———–
对于比拟小的数字,做运算能够间接应用编程语言提供的运算符,然而如果相乘的两个因数十分大,语言提供的数据类型可能就会溢出。一种代替计划就是,运算数以字符串的模式输出,而后模拟咱们小学学习的乘法算术过程计算出后果,并且也用字符串示意。
须要留神的是,num1
和 num2
能够十分长,所以不能够把他们间接转成整型而后运算,惟一的思路就是模拟咱们手算乘法。
比如说咱们手算 123 × 45
,应该会这样计算:
计算 123 × 5
,再计算 123 × 4
,最初错一位相加。这个流程恐怕小学生都能够纯熟实现,然而你是否能 把这个运算过程进一步机械化,写成一套算法指令让没有任何智商的计算机来执行呢?
你看这个简略过程,其中波及乘法进位,波及错位相加,还波及加法进位;而且还有一些不易觉察的问题,比如说两位数乘以两位数,后果可能是四位数,也可能是三位数,你怎么想出一个标准化的解决形式?这就是算法的魅力,如果没有计算机思维,简略的问题可能都没方法自动化解决。
首先,咱们这种手算形式还是太「高级」了,咱们要再「低级」一点,123 × 5
和 123 × 4
的过程还能够进一步合成,最初再相加:
当初 123
并不大,如果是个很大的数字的话,是无奈间接计算乘积的。咱们能够用一个数组在底下接管相加后果:
整个计算过程大略是这样,有两个指针 i,j
在 num1
和 num2
上游走,计算乘积,同时将乘积叠加到 res
的正确地位:
当初还有一个关键问题,如何将乘积叠加到 res
的正确地位,或者说,如何通过 i,j
计算 res
的对应索引呢?
其实,仔细察看之后就发现,num1[i]
和 num2[j]
的乘积对应的就是 res[i+j]
和 res[i+j+1]
这两个地位。
明确了这一点,就能够用代码模拟出这个计算过程了:
string multiply(string num1, string num2) {int m = num1.size(), n = num2.size();
// 后果最多为 m + n 位数
vector<int> res(m + n, 0);
// 从个位数开始逐位相乘
for (int i = m - 1; i >= 0; i--)
for (int j = n - 1; j >= 0; j--) {int mul = (num1[i]-'0') * (num2[j]-'0');
// 乘积在 res 对应的索引地位
int p1 = i + j, p2 = i + j + 1;
// 叠加到 res 上
int sum = mul + res[p2];
res[p2] = sum % 10;
res[p1] += sum / 10;
}
// 后果前缀可能存的 0(未应用的位)int i = 0;
while (i < res.size() && res[i] == 0)
i++;
// 将计算结果转化成字符串
string str;
for (; i < res.size(); i++)
str.push_back('0' + res[i]);
return str.size() == 0 ? "0" : str;}
至此,字符串乘法算法就实现了。
总结一下,咱们司空见惯的一些思维形式,在计算机看来是十分难以做到的。比如说咱们习惯的算术流程并不简单,然而如果让你再进一步,翻译成代码逻辑,并不简略。算法须要将计算流程再简化,通过边算边叠加的形式来失去后果。
俗话教育咱们,不要陷入思维定式,不要程序化,要发散思维,要翻新。但我感觉程序化并不是好事,能够大幅提高效率,减小失误率。算法不就是一套程序化的思维吗,只有程序化能力让计算机帮忙咱们解决简单问题呀!
兴许算法就是一种 寻找思维定式的思维 吧,心愿本文对你有帮忙。