题目

给定两个以字符串形式表示的非负整数 num1num2,返回 num1num2 的乘积,它们的乘积也表示为字符串形式。

示例 1:

1
2
输入: num1 = "2", num2 = "3"
输出: "6"

示例 2:

1
2
输入: num1 = "123", num2 = "456"
输出: "56088"

说明:

  1. num1num2 的长度小于110。
  2. num1num2 只包含数字 0-9。
  3. num1num2 均不以零开头,除非是数字 0 本身。
  4. 不能使用任何标准库的大数类型(比如 BigInteger)直接将输入转换为整数来处理。

分析

两数相乘,假设A有n1位,B有n2位,则乘积结果为n1+n2-1位(最高位无进位)或n1+n2位(最高位有进位),即相乘的结果最多有n1+n2位。

以123与45相乘为例,计算过程实际为错位相乘相加,第2个数的每一位依次与第1个数的每一位错位相乘,再将相乘的结果相加,编程实现就是使用两层for循环,这里使用一个数组来存放最终的字符串形式的结果,在for循环的每一次计算中,都会更新结果数组中的两位,一位是当前计算位,它是某两位置相乘加上本位之前的结果再对10取余,另一位是该结果的进位制,累加到前一位,用于下次计算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    1 2 3 
X 4 5
----------
1 5 → 0 0 0 1 5
1 0 → 0 0 1 1 5
0 5 → 0 0 6 1 5
--------
1 2 → 0 0 7 3 5
0 8 → 0 1 5 3 5
0 4 → 0 5 5 1 5
----------
0 5 5 3 5
↑ ↑ ↑ ↑ ↑
0 1 2 3 4 ← index

C++实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution 
{
public:
string multiply(string num1, string num2)
{
int n1=num1.size();// c++中的size()和length()没有区别,length()是C语言保留下来的
int n2=num2.size();
// A的位数为n1,B的位数为n2,则乘积结果为n1+n2-1位(最高位无进位)或n1+n2位(最高位有进位)
string res(n1+n2,'0');

// 从低位开始相乘
for(int i=n2-1;i>=0;i--)
{
for(int j=n1-1;j>=0;j--)
{
int temp=(res[i+j+1]-'0')+(num1[j]-'0')*(num2[i]-'0');// 上次该位的结果+两数相乘的结果
res[i+j+1]=temp%10+'0';// 当前位赋值(需加'0')(该位最终结果或用于下次计算)
res[i+j]+=temp/10; // 将进位值累加到前一位,res[i+j]已经初始化为'0',只需直接加上int类型
}
}

// 去除首位'0'
for(int i=0;i<n1+n2;i++)
{
if(res[i]!='0')
return res.substr(i);
}

return "0";
}
};

运行结果

输入

1
2
"123"
"45"

输出

1
"5535"