@toc
在实际编程中,我们经常会遇到需要处理大整数的情况。由于编程语言中内置整数类型(如 int、long 等)有其表示范围的限制,当需要处理的整数超出这些范围时,就不能直接使用内置类型进行计算。
一般的解决方式是以两个以字符串形式表示的非负整数 num1 和 num2 的乘法,并将结果也以字符串形式返回。
1 <= num1.length, num2.length <= 200num1 和 num2 只能由数字组成。num1 和 num2 都不包含任何前导零,除了数字 0 本身。要解决这个问题,我们可以模拟手工乘法的过程。在手工乘法中,我们将一个数的每一位与另一个数的每一位相乘,然后将结果相加,并处理进位。具体步骤如下:
num1 或 num2 为 "0",则直接返回 "0"。num1 和 num2 反转。num1.size() + num2.size() 的数组 ret,用于存储中间结果。因为两个数相乘的结果位数不会超过这两个数的位数之和。num1 的每一位与 num2 的每一位相乘,并将结果累加到 ret 数组的相应位置。ret 数组,将每一位的进位加到下一位。#include <string>
#include <algorithm>
class Solution {
public:
string multiply(string num1, string num2)
{
// 先判断是否有一个为0
if(num1 == "0" || num2 == "0")
return "0";
// 反转两个字符串方便操作
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());
// 结果位数不超过两个字符串之和
int size = num1.size() + num2.size();
// 创建存储结果的数组并初始化为0
int* ret = new int[size]();
// 字符串相乘,不考虑进位
for(int i = 0; i < num1.size(); ++i)
{
for(int j = 0; j < num2.size(); ++j)
{
ret[i + j] += (num1[i] - '0') * (num2[j] - '0');
}
}
// 处理进位
for(int i = 0; i < size - 1; ++i)
{
ret[i + 1] += ret[i] / 10;
ret[i] = ret[i] % 10;
}
// 去除前导零
int i = size - 1;
while( (ret[i] == 0) && (size > 1) )
{
--size;
--i;
}
// 转字符串
string s = "";
s.reserve(size);
for(int i = size - 1; i >= 0; --i)
{
s += ('0' + ret[i]);
}
// 释放动态分配的内存
delete[] ret;
return s;
}
};if(num1 == "0" || num2 == "0")
return "0";如果 num1 或 num2 为 "0",则它们的乘积一定为 "0",直接返回即可。
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());使用 std::reverse 函数将 num1 和 num2 反转,这样在后续计算中可以从低位(字符串的起始位置)开始处理。
int size = num1.size() + num2.size();
int* ret = new int[size]();创建一个长度为 num1.size() + num2.size() 的整数数组 ret,并使用 () 进行值初始化,将数组元素都初始化为 0。
for(int i = 0; i < num1.size(); ++i)
{
for(int j = 0; j < num2.size(); ++j)
{
ret[i + j] += (num1[i] - '0') * (num2[j] - '0');
}
}使用两层嵌套循环,将 num1 的每一位与 num2 的每一位相乘,并将结果累加到 ret 数组的相应位置。(num1[i] - '0') 和 (num2[j] - '0') 是将字符转换为对应的数字。
for(int i = 0; i < size - 1; ++i)
{
ret[i + 1] += ret[i] / 10;
ret[i] = ret[i] % 10;
}遍历 ret 数组,将每一位的进位(ret[i] / 10)加到下一位,同时将当前位取模 10 得到该位的最终结果。
int i = size - 1;
while( (ret[i] == 0) && (size > 1) )
{
--size;
--i;
}从结果数组的最高位开始检查,如果该位为 0 且结果长度大于 1,则将长度减 1,继续检查前一位。
string s = "";
s.reserve(size);
for(int i = size - 1; i >= 0; --i)
{
s += ('0' + ret[i]);
}创建一个空字符串 s,并使用 reserve 方法预先分配足够的空间。然后从结果数组的最高位开始,将每一位转换为字符并添加到字符串 s 中。
delete[] ret;由于 ret 是动态分配的数组,使用完后需要使用 delete[] 释放内存,避免内存泄漏。
num1 和 num2 的长度。主要时间开销在于两层嵌套的循环进行逐位相乘。ret。通过以上步骤,我们就可以实现两个大整数的乘法,并将结果以字符串形式返回。这种方法模拟了手工乘法的过程,避免了使用内置的大整数库和直接将输入转换为整数,适用于处理超出内置整数类型表示范围的大整数乘法问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。