Note: The numbers can be arbitrarily large and are non-negative.
[分析] Naive的做法是模拟笔算乘法操作,从高位到低位的顺序将num2 上的每一位同num1 相乘,由于运算顺序从高到低,每次运算时将上一次运算结果后加0,(相当于*10)后同本次乘积结果加和。 高效做法(Method 2)思路:num1 * num2, num2上的每一位依次和num1中的每一位相乘,num2的个位同num1的个位相乘结果包含在最终乘积的个位上,同理num2的个位同num1的十位相乘结果包含在最终乘积的十位上,num2的十位同num1的个位相乘结果也包含在最终乘积的十位上,一般的,num2的第 i 位 同num1的第 j 位相乘结果包含在最终乘积的第 i + j 位,遍历两个数的每一位,可以得到最终乘积各位上的结果。这样得到的乘积各位上可能是两位数,因此还需要处理使得乘积结果各位上为单个数字,处理方式就是依次进位。Method 1有O(m * n)次 *、\、% 以及字符串append操作, O(m * (m + n))次 +, append操作,而Method 2仅有O(m * n)次 *、+ 以及O(m + n)次 \、%、append操作,我们知道除法和取模是最耗时的,所以前者超时也就不难怪了。
// method 2: public String multiply(String num1, String num2) { if (num1 == null || num2 == null || num1.length() == 0 || num2.length() == 0) return null; if (num1.length() < num2.length()) return multiply(num2, num1); if (num2.equals("0")) return "0"; if (num2.equals("1")) return num1; int[] result = new int[num1.length() + num2.length() - 1]; for (int i = num2.length() - 1; i >= 0; i--) { int digit1 = num2.charAt(i) - '0'; for (int j = num1.length() - 1; j >= 0; j--) { result[i + j] += digit1 * (num1.charAt(j) - '0'); } } int carry = 0; for (int i = result.length - 1; i >= 0; i--) { result[i] += carry; carry = result[i] / 10; result[i] %= 10; } StringBuilder val = new StringBuilder(); if (carry > 0) val.append(carry); for (int i = 0; i < result.length; i++) val.append(result[i]); return val.toString(); } // method 1 : public String multiply1(String num1, String num2) { if (num1 == null || num2 == null || num1.length() == 0 || num2.length() == 0) return null; String result = ""; for (int i = 0; i < num2.length(); i++) { result = add(result + '0', multiOneDigit(num1, num2.charAt(i) - '0')); } return result; } private String add(String num1, String num2) { if (num1.length() < num2.length()) { String tmp = num2; num2 = num1; num1 = tmp; } StringBuilder sum = new StringBuilder(); int carry = 0, val = 0; int i = num1.length() - 1, j = num2.length() - 1; while (j >= 0) { val = (num1.charAt(i) - '0') + (num2.charAt(j) - '0'); sum.append(val - 10); // val % 10 carry = val >= 10 ? 1 : 0; // val / 10 i--; j--; } while (i >= 0) { val = (num1.charAt(i--) - '0') + carry; sum.append(val - 10); carry = val >= 10 ? 1 : 0; } if (carry > 0) sum.append(carry); return sum.reverse().toString(); } private String multiOneDigit(String num1, int num2) { StringBuilder result = new StringBuilder(); int carry = 0, val = 0; for (int i = num1.length() - 1; i >= 0; i--) { val = (num1.charAt(i) - '0') * num2 + carry; result.append(val % 10); carry = val / 10; } if (carry > 0) result.append(carry); return result.reverse().toString(); }