问题描述
基于分治思想设计一个大整数乘法的实现程序,可以进行两个大整数的乘法运算,要求时间复杂度小于 O(n2)。
【输入】 分行输入两个大整数,两个整数的长度可以不相同,如果输入的不是合法的 整数,应提示重新输入。
【输出】 计算输出两个大整数的乘法结果。
解法
个人在解的时候参考了很多大神的资料,链接如下:
https://blog.youkuaiyun.com/BigData_Mining/article/details/102884892.
https://blog.youkuaiyun.com/qq_31622541/article/details/110940477
通常算法
算法分析
首先将X和Y分成A,B,C,D
此时将X和Y的乘积转化为图中的式子,把问题转化为求解式子的值
看起来好像有点变化,分析一下:对这个式子,我们一共要进行4次乘法(AC, AD, BC, BD),所以a=4,建立递归方程:
T(n) = 4 * T(n / 2) + θ(n)
通过master定理可以求得该算法的时间复杂度为: T(n) = θ(n ^ 2),跟小学算法的时间复杂度没有区别。
具体算法如下:
分治法
对于这个公式,一共进行了三次乘法(AC,BD,(A+B)(C+D)),因此,a=3.建立递归方程:
T(n) = 3 * T(n / 2) + θ(n),
通过master定理求得时间复杂度为:
T(n) = O(n^log2(3) = O(n^1.59 )。
具体如下:
分治法代码
#include<string>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<sstream>
using namespace std;
class Solution {
public:
/*
这个算法主要分成几个模块来进行实现
1. 在字符串屁股后面添加N个0
2. 字符串相加(这里包括了对负数的操作)
【本算法最复杂部分,因为负数操作的加入可能使得最终费用相对于原本还变高】
3. 把字符串变成偶数串
5. 终止条件:N=1/0的时候
6. 字符串转数字相乘然后再转回字符串
7. 把前面的0给去掉
*/
string multiply(string num1, string num2) {
string result = multi(num1, num2);
result = cut_zero(result);
return result;
}
string multi(string num1, string num2) {
//cout<< "pre:" << num1 <<" " << num2 << endl;
//下面把负号单独处理,生成新的字符串没有负号
int final_flag = 1, flag_1 = 1, flag_2 = 1;
if (num1[0] == '-')
{
flag_1 = -1;
num1 = num1.substr(1);//string substr(size_type _Off = 0,size_type _Count = npos) const;
//_Off:所需的子字符串的起始位置。字符串中第一个字符的索引为 0,默认值为0。
//_Count:复制的字符数目。
//返回值:一个子字符串,从其指定的位置开始。
//即从1位置开始复制原字符串到目标字符串
}
if (num2[0] == '-')
{
flag_2 = -1;
num2 = num2.substr(1);
}
// 如果异号,我们采用
if (flag_1 + flag_2 == 0)
{
final_flag = -1;
}
int maxsize = num1.size() > num2.size() ? num1.size() : num2.size();
if (maxsize % 2 == 1) //把奇数长度的字符串改为偶数长度的,并对齐
{
maxsize += 1;
}
num1 = to_odd_string(num1, maxsize);//在字符串前面补零
num2 = to_odd_string(num2, maxsize);
//cout<< "dealed:" << num1 <<" " << num2 << endl;
if (judge_zero(num1) || judge_zero(num2)) //判断字符串中是否含有零,因为零乘任何数都是零,所以返回零
{
return "0";
}
if (maxsize <= 4) //位数小于4,直接转换为int型计算
{
string res = convert_multi(num1, num2);
if (final_flag == -1)
{
string ret = "-";
res = ret + res;//把负号加到字符串前面
}
// cout << "result:" << res << endl;
return res;
}
int N_2 = num1.size() / 2;
string A_1 = num1.substr<