[Leetcode 43 Multiply Strings]大数乘法,回到乘法本身的“最基础”去优化

来源:互联网 发布:怎么开网络博客 编辑:程序博客网 时间:2024/06/06 05:27

大数乘法是笔试面试中经常会被考到的一个题目,它要求我们对超出long类型范围的大整数用字符串进行处理,加减乘除都会考到,我们先试着写一下大数加法的代码:

    // Add Big Integer    public String add(String num1, String num2) {        if(num2.length() > num1.length()){            // return add(String num2, String num1);            String t = num1;            num1 = num2;            num2 = t;        }        if(num2.equals("0")) return num1;        char[] n1 = num1.toCharArray();        char[] n2 = num2.toCharArray();        String res = "";        int d = 0;        int i=n1.length-1, j=n2.length-1;        for(;j>=0; i--, j--){            int a = (n1[i]-'0') + (n2[j]-'0') + d;            d = a / 10;            res = "" + (a % 10) + res;        }        // when d==0 it could be optimized.        for(;i>=0; i--){            int a = (n1[i]-'0') + d;            d = a / 10;            res = "" + (a % 10) + res;        }        if(d>0) res = "" + d + res;        return res;    }

按照思维惯性,我们会把乘法拆成加法去做,注意以下几点
1、把String变成char数组处理更好,用较长的char数组储存结果最后再转成String是很好的选择
2、去掉前导0
3、个位加法进位最多进1
所以上述代码有很多可以优化的地方。

所以两个大数相乘就拆成了下述两步:
1、一个大数与另一个大数的每一位相乘(若干个第一个大数自身相加)
2、得到的结果补0位对齐后再相加
不贴代码了,大家都能理解这个意思。


但是这个题目的更好的解决方式是要回到乘法的“最基础“。让我们看一下下图(来自某大神):

leetcode 43 Multiply Strings

这个竖式和咱们最开始学乘法时候的竖式是有区别的,它把一个数乘以另一个数的一位分得更细了。

public class Solution {    public String multiply(String num1, String num2) {        int m = num1.length(), n = num2.length();        int[] pos = new int[m + n];        for(int i = m - 1; i >= 0; i--) {            for(int j = n - 1; j >= 0; j--) {                int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0');                 int p1 = i + j, p2 = i + j + 1;                int sum = mul + pos[p2];                pos[p1] += sum / 10;                pos[p2] = (sum) % 10;            }        }          StringBuilder sb = new StringBuilder();        for(int p : pos) if(!(sb.length() == 0 && p == 0)) sb.append(p);        return sb.length() == 0 ? "0" : sb.toString();    }}

读懂上图和代码要了解三件事情:
1、位数为m和n的两数相乘,结果的位数最多为m+n(99*9=891,999*99=98901),所以pos数组的长度为m+n
2、(关键)一个数的第i高位与另一个数的第j高位相乘,得到的两位数结果(此时个位1看成01),第一位应加在结果的第i+j高位,第二位应加在结果的第i+j+1高位。
3、结果需要跳过前导0

这三点看懂了,本题一下子就开朗了,只要在面试的时候画出图中的式子,并跟面试官说出上面三件事情,代码部分只是体力活了。

阅读全文
0 0
原创粉丝点击