对于比较小的数字,作运算能够直接使用编程语言提供的运算符,可是若是相乘的两个因数很是大,语言提供的数据类型可能就会溢出。一种替代方案就是,运算数以字符串的形式输入,而后模仿咱们小学学习的乘法算术过程计算出结果,而且也用字符串表示。git
须要注意的是,num1
和 num2
能够很是长,因此不能够把他们直接转成整型而后运算,惟一的思路就是模仿咱们手算乘法。算法
好比说咱们手算 123 × 45
,应该会这样计算:编程
计算 123 × 5
,再计算 123 × 4
,最后错一位相加。这个流程恐怕小学生均可以熟练完成,可是你是否能把这个运算过程进一步机械化,写成一套算法指令让没有任何智商的计算机来执行呢?数组
PS:我认真写了 100 多篇原创,手把手刷 200 道力扣题目,所有发布在 labuladong的算法小抄,持续更新。建议收藏,按照个人文章顺序刷题,掌握各类算法套路后投再入题海就如鱼得水了。编程语言
你看这个简单过程,其中涉及乘法进位,涉及错位相加,还涉及加法进位;并且还有一些不易察觉的问题,好比说两位数乘以两位数,结果多是四位数,也多是三位数,你怎么想出一个标准化的处理方式?这就是算法的魅力,若是没有计算机思惟,简单的问题可能都没办法自动化处理。ide
首先,咱们这种手算方式仍是太「高级」了,咱们要再「低级」一点,123 × 5
和 123 × 4
的过程还能够进一步分解,最后再相加:学习
如今 123
并不大,若是是个很大的数字的话,是没法直接计算乘积的。咱们能够用一个数组在底下接收相加结果:spa
整个计算过程大概是这样,有两个指针 i,j
在 num1
和 num2
上游走,计算乘积,同时将乘积叠加到 res
的正确位置:翻译
如今还有一个关键问题,如何将乘积叠加到 res
的正确位置,或者说,如何经过 i,j
计算 res
的对应索引呢?3d
其实,细心观察以后就发现,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; }
至此,字符串乘法算法就完成了。
PS:我认真写了 100 多篇原创,手把手刷 200 道力扣题目,所有发布在 labuladong的算法小抄,持续更新。建议收藏,按照个人文章顺序刷题,掌握各类算法套路后投再入题海就如鱼得水了。
总结一下,咱们习觉得常的一些思惟方式,在计算机看来是很是难以作到的。好比说咱们习惯的算术流程并不复杂,可是若是让你再进一步,翻译成代码逻辑,并不简单。算法须要将计算流程再简化,经过边算边叠加的方式来获得结果。
俗话教育咱们,不要陷入思惟定式,不要程序化,要发散思惟,要创新。但我以为程序化并非坏事,能够大幅提升效率,减少失误率。算法不就是一套程序化的思惟吗,只有程序化才能让计算机帮助咱们解决复杂问题呀!
也许算法就是一种寻找思惟定式的思惟吧,但愿本文对你有帮助。
_____________