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. // @author 连城 (http://weibo.com/lianchengzju)
  3. // 一个字符对应一个int
  4. // 时间复杂度O(n*m),空间复杂度O(n+m)
  5. typedef vector bigint;
  6. bigint make_bigint(string const& repr) {
  7. bigint n;
  8. transform(repr.rbegin(), repr.rend(), back_inserter(n),
  9. [](char c) { return c - '0'; });
  10. return n;
  11. }
  12. string to_string(bigint const& n) {
  13. string str;
  14. transform(find_if(n.rbegin(), prev(n.rend()),
  15. [](char c) { return c > '\0'; }), n.rend(), back_inserter(str),
  16. [](char c) { return c + '0'; });
  17. return str;
  18. }
  19. bigint operator*(bigint const& x, bigint const& y) {
  20. bigint z(x.size() + y.size());
  21. for (size_t i = 0; i < x.size(); ++i)
  22. for (size_t j = 0; j < y.size(); ++j) {
  23. z[i + j] += x[i] * y[j];
  24. z[i + j + 1] += z[i + j] / 10;
  25. z[i + j] %= 10;
  26. }
  27. return z;
  28. }
  29. class Solution {
  30. public:
  31. string multiply(string num1, string num2) {
  32. return to_string(make_bigint(num1) * make_bigint(num2));
  33. }
  34. };

代码2

  1. // Multiply Strings
  2. // 9个字符对应一个int64_t
  3. // 时间复杂度O(n*m/81),空间复杂度O((n+m)/9)
  4. /** 大整数类. */
  5. class BigInt {
  6. public:
  7. /**
  8. * @brief 构造函数,将字符串转化为大整数.
  9. * @param[in] s 输入的字符串
  10. * @return 无
  11. */
  12. BigInt(string s) {
  13. vector<int64_t> result;
  14. result.reserve(s.size() / RADIX_LEN + 1);
  15. for (int i = s.size(); i > 0; i -= RADIX_LEN) { // [i-RADIX_LEN, i)
  16. int temp = 0;
  17. const int low = max(i - RADIX_LEN, 0);
  18. for (int j = low; j < i; j++) {
  19. temp = temp * 10 + s[j] - '0';
  20. }
  21. result.push_back(temp);
  22. }
  23. elems = result;
  24. }
  25. /**
  26. * @brief 将整数转化为字符串.
  27. * @return 字符串
  28. */
  29. string toString() {
  30. stringstream result;
  31. bool started = false; // 用于跳过前导0
  32. for (auto i = elems.rbegin(); i != elems.rend(); i++) {
  33. if (started) { // 如果多余的0已经都跳过,则输出
  34. result << setw(RADIX_LEN) << setfill('0') << *i;
  35. } else {
  36. result << *i;
  37. started = true; // 碰到第一个非0的值,就说明多余的0已经都跳过
  38. }
  39. }
  40. if (!started) return "0"; // 当x全为0时
  41. else return result.str();
  42. }
  43. /**
  44. * @brief 大整数乘法.
  45. * @param[in] x x
  46. * @param[in] y y
  47. * @return 大整数
  48. */
  49. static BigInt multiply(const BigInt &x, const BigInt &y) {
  50. vector<int64_t> z(x.elems.size() + y.elems.size(), 0);
  51. for (size_t i = 0; i < y.elems.size(); i++) {
  52. for (size_t j = 0; j < x.elems.size(); j++) { // 用y[i]去乘以x的各位
  53. // 两数第i, j位相乘,累加到结果的第i+j位
  54. z[i + j] += y.elems[i] * x.elems[j];
  55. if (z[i + j] >= BIGINT_RADIX) { // 看是否要进位
  56. z[i + j + 1] += z[i + j] / BIGINT_RADIX; // 进位
  57. z[i + j] %= BIGINT_RADIX;
  58. }
  59. }
  60. }
  61. while (z.back() == 0) z.pop_back(); // 没有进位,去掉最高位的0
  62. return BigInt(z);
  63. }
  64. private:
  65. typedef long long int64_t;
  66. /** 一个数组元素对应9个十进制位,即数组是亿进制的
  67. * 因为 1000000000 * 1000000000 没有超过 2^63-1
  68. */
  69. const static int BIGINT_RADIX = 1000000000;
  70. const static int RADIX_LEN = 9;
  71. /** 万进制整数. */
  72. vector<int64_t> elems;
  73. BigInt(const vector<int64_t> num) : elems(num) {}
  74. };
  75. class Solution {
  76. public:
  77. string multiply(string num1, string num2) {
  78. BigInt x(num1);
  79. BigInt y(num2);
  80. return BigInt::multiply(x, y).toString();
  81. }
  82. };

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