动态规划 字符串相乘

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

示例 1:

输入: num1 = “2”, num2 = “3”
输出: “6”
示例 2:

输入: num1 = “123”, num2 = “456”
输出: “56088”
说明:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/multiply-strings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。*/

最近在联系动态规划的问题,因此本题使用了动态规划的思想去解决。(但是,本题的最优算法不是动态规划。)
最简单的算法之一,是转化为int,相乘然后在输入到str函数。

动态规划求解:
以123,456为例子。
string num1={“123”};
string unm2={“456”};
记图为m;

n1012
n2
04812
151015
261218

(n1为num1,n2为num2)

设答案已经求出。如果,我们需要十位数的值。我们需要知道

  1. 个位数进了几。
  2. num2的个位数乘以num2的十位数。
  3. num2的十位数乘以num2的个位数。

如果需要求百位数的值。我们需要知道:

  1. 十位数进了几。
  2. num2的个位数乘以num1的百位数。
  3. num2的十位数乘以num1的十位数。
  4. num2的百位数乘以num1的个位数。

再回到这张图
容易发现,m[2][2]为个位数的成绩。从m[2][2]的位置做斜对角线,一直到m[0][0]。发现,每一个斜对角线的和对应着不加进位时,该位的值。同时,算出的结果大于0的部分进到下一位。

那么,我们要求第n位的时候。(设个位是第0位)。需要知道n-1位的值。
求n-1位的时候需要知道n-2位的值。
因此我们可以用一个int b将n-1为存下来。
事实上我们要保存的是b/10。

class Solution {
public:
    string multiply(string num1, string num2) {

   using namespace std;
   int m[150][150]; 
	//	cout << num1[0] << num2;
	int n1 = num1.length(), n2 = num2.length();
	for (int i = 0; i < 150; i++) {//初始化数组为0
		for (int j = 0; j < 150; j++) {
			m[i][j] = 0;
		}
	}
	for (int i = 0; i < n1; i++) { //填表格
		for (int j = 0; j < n2; j++) {
			m[i][j] = (num1[i] - 48) * (num2[j] - 48);
		}
	}
	for (int i = 0; i < n1; i++) {
		for (int j = 0; j < n2; j++) {
			cout << m[i][j] << ' ';
		}
		cout << endl;
	}
	string sum1;//从个位开始填填入sum;然后逆转即可;
	//对角线向上乘
	//int n1 = num1.length() - 1;
	//int n2 = num2.length() - 1;
	n1--; n2--;
	int n3 = n1 + n2;
	//相加为n3的时候
	int b = 0;
	for (int i = n3; i >= 0; i--) {
		int sum = 0;
		for (int j = n2; j >= 0 && (i-j)<=n1; j--) {//因为我定义的数组足够大而且初始化为0了所以条件可以省略一些
			if (j >= 0 && (i - j) >= 0)sum += m[i-j][j];
			if (j < 0 || (i - j) < 0)continue;
			//			cout << sum<<endl;
		}
		//		cout << sum << endl;
		sum += b;
		b = sum / 10;
		//		cout << sum <<'x'<< endl;
		sum1+= sum % 10 +48;
	}
            if(b!=0){
            sum1+=b+48;
        }
	string sum2;

 int flag=0;
	for (int i = sum1.length() - 1; i >= 0; i--) {
		sum2 += sum1[i];
        if(sum1[i]==48)flag++;
	}
 string sum3={'0'};
if(flag==sum1.length()) return sum3;
else	return sum2;
    }

};

代码还可以优化。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值