Multiply Strings

描述

Given two numbers represented as strings, return multiplication of the numbers as a string.

Note: The numbers can be arbitrarily large and are non-negative.

分析

高精度乘法。

常见的做法是将字符转化为一个int,一一对应,形成一个int数组。但是这样很浪费空间,一个int32的最大值是2^{31}-1=2147483647,可以与9个字符对应,由于有乘法,减半,则至少可以与4个字符一一对应。一个int64可以与9个字符对应。

代码1

  1. // Multiply Strings
  2. // 一个字符对应一个int
  3. // 时间复杂度O(n*m),空间复杂度O(n+m)
  4. public class Solution {
  5. public String multiply(String num1, String num2) {
  6. BigInt bigInt1 = new BigInt(num1);
  7. BigInt bigInt2 = new BigInt(num2);
  8. BigInt result = BigInt.multiply(bigInt1, bigInt2);
  9. return result.toString();
  10. }
  11. // 一个字符对应一个int
  12. static class BigInt {
  13. private final int[] d;
  14. public BigInt(String s) {
  15. this.d = fromString(s);
  16. }
  17. public BigInt(int[] d) {
  18. this.d = d;
  19. }
  20. private static int[] fromString(String s) {
  21. int[] d = new int[s.length()];
  22. for (int i = s.length() - 1, j = 0; i >= 0; --i)
  23. d[j++] = Character.getNumericValue(s.charAt(i));
  24. return d;
  25. }
  26. @Override
  27. public String toString() {
  28. final StringBuilder sb = new StringBuilder();
  29. for (int i = d.length - 1; i >= 0; --i) {
  30. sb.append(Character.forDigit(d[i], 10));
  31. }
  32. return sb.toString();
  33. }
  34. public static BigInt multiply(BigInt x, BigInt y) {
  35. int[] z = new int[x.d.length + y.d.length];
  36. for (int i = 0; i < x.d.length; ++i) {
  37. for (int j = 0; j < y.d.length; ++j) {
  38. z[i + j] += x.d[i] * y.d[j];
  39. z[i + j + 1] += z[i + j] / 10;
  40. z[i + j] %= 10;
  41. }
  42. }
  43. // find the first 0 from right to left
  44. int i = z.length - 1;
  45. for (; i > 0 && z[i] == 0; --i) /* empty */;
  46. if (i == z.length - 1) {
  47. return new BigInt(z);
  48. } else { // make a copy
  49. int[] tmp = new int[i + 1];
  50. System.arraycopy(z, 0, tmp, 0, i + 1);
  51. return new BigInt(tmp);
  52. }
  53. }
  54. }
  55. }

代码2

  1. // Multiply Strings
  2. // 9个字符对应一个 long
  3. // 时间复杂度O(n*m),空间复杂度O(n+m)
  4. public class Solution {
  5. public String multiply(String num1, String num2) {
  6. BigInt bigInt1 = BigInt.fromString(num1);
  7. BigInt bigInt2 = BigInt.fromString(num2);
  8. BigInt result = BigInt.multiply(bigInt1, bigInt2);
  9. return result.toString();
  10. }
  11. // 9个字符对应一个 long
  12. static class BigInt {
  13. /** 一个数组元素对应9个十进制位,即数组是亿进制的
  14. * 因为 1000000000 * 1000000000 没有超过 2^63-1
  15. */
  16. final static int BIGINT_RADIX = 1000000000;
  17. final static int RADIX_LEN = 9;
  18. /** 万进制整数. */
  19. private final long[] digits;
  20. public BigInt(long[] digits) {
  21. this.digits = digits;
  22. }
  23. private static BigInt fromString(String s) {
  24. long[] digits;
  25. if (s.length() % RADIX_LEN == 0) {
  26. digits = new long[s.length() / RADIX_LEN];
  27. } else {
  28. digits = new long[s.length() / RADIX_LEN + 1];
  29. }
  30. for (int i = s.length(), k = 0; i > 0; i -= RADIX_LEN) {
  31. long tmp = 0;
  32. for (int j = Math.max(0, i - RADIX_LEN); j < i; ++j) {
  33. tmp = tmp * 10 + Character.getNumericValue(s.charAt(j));
  34. }
  35. digits[k++] = tmp;
  36. }
  37. return new BigInt(digits);
  38. }
  39. @Override
  40. public String toString() {
  41. final StringBuilder sb = new StringBuilder(
  42. Long.toString(digits[digits.length-1]));
  43. for (int i = digits.length - 2; i >= 0; --i) {
  44. sb.append(String.format("%0" + RADIX_LEN + "d", digits[i]));
  45. }
  46. return sb.toString();
  47. }
  48. public static BigInt multiply(BigInt x, BigInt y) {
  49. long[] z = new long[x.digits.length + y.digits.length];
  50. for (int i = 0; i < x.digits.length; ++i) {
  51. for (int j = 0; j < y.digits.length; ++j) {
  52. z[i + j] += x.digits[i] * y.digits[j];
  53. z[i + j + 1] += z[i + j] / BIGINT_RADIX;
  54. z[i + j] %= BIGINT_RADIX;
  55. }
  56. }
  57. // find the first 0 from right to left
  58. int i = z.length - 1;
  59. for (; i > 0 && z[i] == 0; --i) /* empty */;
  60. if (i == z.length - 1) {
  61. return new BigInt(z);
  62. } else { // make a copy
  63. long[] tmp = new long[i + 1];
  64. System.arraycopy(z, 0, tmp, 0, i + 1);
  65. return new BigInt(tmp);
  66. }
  67. }
  68. }
  69. }

原文: https://soulmachine.gitbooks.io/algorithm-essentials/content/java/simulation/multiply-strings.html