跳到主要内容

LeetCode 43. 字符串相乘

本节目标

把每对数字的乘积累加到长度为 m + n 的数组,并从低位向高位处理进位。

这道题延续解析与大整数的逐位算术模板:不构造每一行中间字符串,而是把所有数字对的贡献累加到固定长度数组。

查看原题

题意与约束

给定两个非负十进制整数字符串,不能直接使用大整数库,返回两数的乘积。任意一个输入为 0 时,结果必须是单个字符 0

定位每一对数字

长度为 mn 的两个数相乘,结果最多有 m + n 位。若两个数字的下标分别为 ij,其乘积应先累加到数组位置 i + j + 1;该位置产生的进位再加到前一位 i + j

跳过前导零

数组前端可能保留零,例如 123 × 456 的数组长度为六但答案只有五位。完成全部累加后跳过前导零;提前特判零输入可以避免得到空字符串。

代码实现

C++17
#include <string>
#include <vector>

using namespace std;

class Solution {
public:
string multiply(string num1, string num2) {
if (num1 == "0" || num2 == "0") {
return "0";
}

int firstSize = static_cast<int>(num1.size());
int secondSize = static_cast<int>(num2.size());
vector<int> digits(firstSize + secondSize);

for (int firstIndex = firstSize - 1; firstIndex >= 0; firstIndex--) {
for (int secondIndex = secondSize - 1; secondIndex >= 0; secondIndex--) {
int product = (num1[firstIndex] - '0') * (num2[secondIndex] - '0');
int position = firstIndex + secondIndex + 1;
int sum = digits[position] + product;
digits[position] = sum % 10;
digits[position - 1] += sum / 10;
}
}

string result;
int index = 0;
while (index < static_cast<int>(digits.size()) && digits[index] == 0) {
index++;
}
while (index < static_cast<int>(digits.size())) {
result.push_back(static_cast<char>('0' + digits[index]));
index++;
}

return result;
}
};

复杂度分析

设两个字符串长度为 mn,时间复杂度为 O(m * n),额外空间复杂度为 O(m + n)

易错点

  • 结果数组开成 m + n - 1,遗漏最高位进位。
  • 把乘积位置写成 i + j,使所有数字错位一位。
  • 忘记跳过前导零,或零输入时返回空串。

模式迁移

长整数的乘法、进制转换中的逐位累加都可先固定每个局部贡献的位置,再按进位规则归并;若需要更高性能,再学习分治乘法。