[LeetCode]Multiply Strings

13 篇文章 0 订阅
11 篇文章 0 订阅

一、问题描述:

Given two numbers represented as strings, return multiplication of the numbers as a string.

Note:

  • The numbers can be arbitrarily large and are non-negative.
  • Converting the input string to integer is NOT allowed.
  • You should NOT use internal library such as BigInteger.
二、问题分析:
题目就是模拟乘法操作,而且还是非负数,这样就比较简单了。
原本用了分治的方法去做,而且明显时间复杂度比模拟低,但竟然超时了......为了避免以后重复造轮子,这次把模拟乘法的代码贴出来。其中注释部分去掉之后为正负通用的乘法。
还有一个比较蛋疼的是命令行下to_string()总是找不到,干脆自己写一个好了(虽然这道题只是在调试的时候用了下...)
public:
    string multiply(string num1, string num2) {
    	string ans(num1.length()+num2.length(), '0');
    	int PN = 1, n = ans.length();
        if (num1.length()<1 || num2.length()<1) return ans;
        if (num1 == "0" || num2 == "0") return "0";
        // if (num1 == "-") {
        // 	PN *= (-1);
        // 	num1 = num1.substr(1, num1.length()-1);
        // }
        // if (num2 == "-") {
        // 	PN *= (-1);
        // 	num2 = num2.substr(1, num2.length()-1);
        // }
        for (int i = num1.length()-1; i >= 0; --i, --n) {
        	int carry = 0, pos = n-1;
        	for (int j = num2.length()-1; j >= 0; --j, --pos) {
        		int charMult = (num1[i]-'0')*(num2[j]-'0')+carry+ans[pos]-'0';
        		carry = charMult/10;
        		ans[pos] = charMult%10+'0';
        	}
        	while (carry) {
        		int charAdd = (ans[pos]-'0')+carry;
        		carry = charAdd/10;
        		ans[pos--] = charAdd%10+'0';
        	}
        }
        int i = 0;
        for(; i<ans.length() && ans[i]=='0'; i++);
        ans = ans.substr(i, ans.length()-i);
        // if (PN == -1) ans = "-"+ans;
        return ans;
    }
private:
	string to_string(int i) {
		stringstream ss;
		ss << i;
		string s;
		ss >> s;
		return s;
	}

==================================================================================================================
来来来,每次写高精度分治乘都是一趟血雨腥风。。。
C++版的来一发:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#define PI (acos(-1.0))
#define EPS (1e-8)
#define INF (1<<30)
using namespace std;
string add(string x, string y);
string sub(string x, string y);
string multiply(string x, string y);
string to_string(int i) {
	stringstream ss;
	ss << i;
	string s;
	ss >> s;
	return s;
}
string add(string x, string y) {
	string s1(x);
	string s2(y);
	if (s1[0]=='-' && s2[0]!='-') return sub(s2, s1.substr(1));
	if (s1[0]!='-' && s2[0]=='-') return sub(s1, s2.substr(1));
	
	string sign;
	if (s1[0] == '-') {
		sign = "-";
		s1 = s1.substr(1);
		s2 = s2.substr(1);
	}
	else sign = "";

	while (s1[0] == '0') s1 = s1.substr(1);
	if (s1.length() == 0) s1 = "0";
	while (s2[0] == '0') s2 = s2.substr(1);
	if (s2.length() == 0) s2 = "0";

	string ans(max(s1.length(), s2.length())+1, '0');
	int s1_pos=s1.length()-1, s2_pos=s2.length()-1, carry=0, pos=ans.length()-1;
	for (; s1_pos>=0 && s2_pos>=0; s1_pos--, s2_pos--) {
		int val = s1[s1_pos]-'0'+s2[s2_pos]-'0'+carry;
		carry = val/10;
		ans[pos--] = val%10+'0';
	}
	while (s1_pos >= 0) {
		int val = s1[s1_pos--]-'0'+carry;
		carry = val/10;
		ans[pos--] = val%10+'0';
	}
	while (s2_pos >= 0) {
		int val = s2[s2_pos--]-'0'+carry;
		carry = val/10;
		ans[pos--] = val%10+'0';
	}
	if (carry)  ans[pos--] = '1';
	for (int i = 0; i <= ans.length(); ++i) {
		if (ans[i] != '0') {
			pos = i;
			break;
		}
	}

	// cout << "add: " << x << "," << y << endl;
	// cout << "add answer: " << sign+ans << endl;
	if (pos == ans.length()) return "0";
	return sign+ans.substr(pos);
}
string sub(string x, string y) {
	string s1(x);
	string s2(y);
	if (s1[0]=='-' && s2[0]!='-') return "-"+add(s2, s1.substr(1));
	if (s1[0]!='-' && s2[0]=='-') return "-"+add(s1, s2.substr(1));
	
	string sign;
	if (s1[0] == '-') {
		sign = "-";
		s1 = s1.substr(1);
		s2 = s2.substr(1);
	}
	else sign = "";

	while (s1[0] == '0') s1 = s1.substr(1);
	if (s1.length() == 0) s1 = "0";
	while (s2[0] == '0') s2 = s2.substr(1);
	if (s2.length() == 0) s2 = "0";

	if (s1.length()<s2.length() || (s1.length()==s2.length() && s1<s2)) {
		string tmp = s2;
		s2 = s1;
		s1 = tmp;
		if (sign.length() == 0) sign = "-";
		else sign = "";
	}
	string ans(s1.length()+1, '0');

	int s1_pos=s1.length()-1, s2_pos=s2.length()-1, carry=0, pos=ans.length()-1;
	for (; s1_pos>=0 && s2_pos>=0; s1_pos--, s2_pos--) {
		int val = (s1[s1_pos]-'0'+10)-(s2[s2_pos]-'0')-carry;
		if (val >= 10) {
			ans[pos--] = val%10+'0';
			carry = 0;
		}
		else {
			ans[pos--] = val+'0';
			carry = 1;
		}
	}
	while (s1_pos >= 0) {
		int val = s1[s1_pos--]-'0'+10-carry;
		if (val >= 10) {
			ans[pos--] = val%10+'0';
			carry = 0;
		}
		else {
			ans[pos--] = val+'0';
			carry = 1;
		}
	}
	for (int i = 0; i <= ans.length(); ++i) {
		if (ans[i] != '0') {
			pos = i;
			break;
		}
	}
	// cout << "sub: " << x << "," << y << endl;
	// cout << "sub answer: " << sign+ans << endl;
	if (pos == ans.length()) return "0";
	return sign+ans.substr(pos);
}
string multiply(string x, string y) {
	int sign = 1;
	string s1(x);
	string s2(y);
	if (s1=="0" || s2=="0") return "0";
	if (s1[0] == '-') {
		sign *= (-1);
		s1 = s1.substr(1);
	}
	if (s2[0] == '-') {
		sign *= (-1);
		s2 = s2.substr(1);
	}
	if (s1.length()==1 && s2.length()==1) {
		int res = (s1[0]-'0')*(s2[0]-'0');
		string ans = to_string(res);
		if (sign == -1) ans = "-"+ans;
		return ans;
	}

	int len = max(s1.length(), s2.length());
	while (s1.length() < len) s1 = "0"+s1;
	while (s2.length() < len) s2 = "0"+s2;
	string a = s1.substr(0, len/2);
	string b = s1.substr(len/2);
	string c = s2.substr(0, len/2);
	string d = s2.substr(len/2);

	string part1 = multiply(a, c);
	string part2 = multiply(b, d);

	// cout << "part1 = " << part1 << endl;
	// cout << "part2 = " << part2 << endl;
	
	string part3 = sub(a, b);
	string part4 = sub(d, c);

	// cout << "part3 = " << part3 << endl;
	// cout << "part4 = " << part4 << endl;
	string part5 = multiply(part3, part4);

	// cout << "part5 = " << part5 << endl;
	part3 = add(part5, part1);
	// cout << "part3 = " << part3 << endl;
	part3 = add(part3, part2);
	// cout << "part3 = " << part3 << endl;

	int add_zero = len-len/2;
	if (part1 != "0") for (int i = 0; i < add_zero*2; ++i) part1 = part1+"0";
	if (part3 != "0") for (int i = 0; i < add_zero; ++i) part3 = part3+"0";
	// cout << "part1 = " << part1 << endl;
	// cout << "part3 = " << part3 << endl;

	string ans = add(add(part1, part2), part3);
	// cout << "ans = " << ans << endl;
	int pos = 0;
	for (int i = 0; i <= ans.length(); ++i) {
		if (ans[i] != '0') {
			pos = i;
			break;
		}
	}
	if (sign == -1) ans = "-"+ans;
	// cout << "part: " << part1 << "," << part2 << "," << part3<< endl;
	// cout << "multiply: " << x << "," << y << endl;
	// cout << "multiply ans = " << ans << endl;
	return ans;
}
int main(int argc, char const *argv[]) {
	string s1, s2;
	while (cin >> s1 >> s2) {
		string result = multiply(s1, s2);
		cout << result << endl;
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值