🦄个人主页: 起名字真南
🦄个人专栏:【数据结构初阶】 【C语言】 【C++】 【OJ题解】
目录
- [1. 引言](#1. 引言)
- [2. 题目分析](#2. 题目分析)
- [3. 解题思路](#3. 解题思路)
- [4. C++代码实现](#4. C++代码实现)
- [5. 代码详解](#5. 代码详解)
- [6. 时间和空间复杂度分析](#6. 时间和空间复杂度分析)
- [7. 边界情况分析](#7. 边界情况分析)
- [8. 总结](#8. 总结)
1. 引言
在开发中,有时我们需要处理超出标准整数范围的大数运算。例如,两个200位的数字相乘,结果可能多达400位,而这远超出
int
或long
的存储能力。本教程将深入讲解如何使用C++实现字符串形式的数字相乘,完全不依赖BigInteger
或类似大数库的支持。
2. 题目分析
题目要求我们给定两个非负整数字符串num1
和num2
,返回它们的乘积结果字符串。考虑到每个字符串长度可能达200位,所以乘积结果最多有400位,我们不能简单地将字符串转成整数相乘。相反,我们可以通过模拟手动乘法的方式来解决这个问题。
示例:
- 示例 1:
- 输入:
num1 = "2"
,num2 = "3"
- 输出:
"6"
- 输入:
- 示例 2:
- 输入:
num1 = "123"
,num2 = "456"
- 输出:
"56088"
- 输入:
3. 解题思路
该题目可以用模拟手动乘法来实现。我们可以把计算步骤划分如下:
- 逐位相乘:倒序遍历两个字符串,将每一位相乘,计算出相应的部分积。
- 累加进位:在累加结果时,处理进位并确保每个位的值不超过9。
- 去除前导零:最终结果可能有前导零,将其去除。
4. C++代码实现
以下为详细的C++代码实现:
cpp
class Solution {
public:
string multiply(string num1, string num2) {
// 特殊情况:如果任意一个数字为 "0",返回 "0"
if (num1 == "0" || num2 == "0") {
return "0";
}
// 初始化结果字符串,长度为 num1.size() + num2.size()
size_t n1 = num1.size();
size_t n2 = num2.size();
string result(n1 + n2, '0');
// 倒序遍历 num1 和 num2
for (int i = n1 - 1; i >= 0; i--) {
for (int j = n2 - 1; j >= 0; j--) {
// 将字符转换为整数
int x = num1[i] - '0';
int y = num2[j] - '0';
int mul = x * y; // 单个位的乘积
// 确定结果中的位置
int p1 = i + j; // 进位位置
int p2 = i + j + 1; // 当前位位置
// 叠加当前的乘积到结果
int sum = mul + (result[p2] - '0');
result[p2] = (sum % 10) + '0'; // 当前位
result[p1] += sum / 10; // 进位
}
}
// 去除前导零
size_t startpos = result.find_first_not_of('0');
if (startpos != string::npos) {
return result.substr(startpos);
}
return "0";
}
};
5. 代码详解
-
特殊情况处理 :首先检查
num1
或num2
是否为"0"
,若是则直接返回"0"
。 -
结果初始化 :使用
string result(n1 + n2, '0')
初始化结果字符串,长度为n1 + n2
,确保足够容纳乘积结果。初始值为'0',便于后续累加操作。 -
倒序遍历相乘:
- 字符转数字 :
num1[i] - '0'
和num2[j] - '0'
用于将字符转为整数。 - 单个位乘积 :计算单个位乘积
mul = x * y
。 - 位置确定 :
p1
和p2
分别表示当前乘积的进位位置和当前位位置。 - 累加到结果 :通过
sum = mul + (result[p2] - '0')
将当前乘积叠加到结果字符串中,并更新result[p2]
为当前位,同时将进位累加到result[p1]
。
- 字符转数字 :
-
去除前导零 :
result.find_first_not_of('0')
找到第一个非零位的索引,如果找到则返回从该位置截取的子字符串,否则返回"0"。
6. 时间和空间复杂度分析
- 时间复杂度 :O(n * m),其中
n
和m
是num1
和num2
的长度。每一位的乘积与累加均在常数时间完成。 - 空间复杂度:O(n + m),结果字符串的存储需求。
7. 边界情况分析
- 输入为"0":任何一个输入为"0"时,结果直接为"0"。
- 输入较短或较长:该算法不依赖特定的输入长度,能够处理长达200位的输入。
- 前导零问题 :代码中通过
find_first_not_of
函数有效移除了前导零,确保结果的正确性。
8. 总结
本算法通过手动模拟乘法的方式实现了字符串表示的大数乘法。在未来优化中,可以考虑更高效的大数乘法算法(如Karatsuba算法),进一步降低时间复杂度。
希望这篇文章能帮助大家更好地理解字符串乘法的实现原理,提升解决大数计算的能力。