Loading

【leetcode】43. Multiply Strings(大数相乘)

  Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string. Note: You must not use any built-in BigInteger library or convert the inputs to integer directly.
  暴力法 转换为数值型变量再进行相乘 但是对于大数会溢出
       
class Solution {
public:
    string multiply(string num1, string num2) {
        if(num1=="0" || num2=="0") return "0";
        long long num1_=sstonum(num1);
        long long num2_=sstonum(num2);
        long long result=num1_*num2_;
        return numtoss(result);   
    }
    
    long long sstonum(string num){
        long long res=0;
        for(char nn:num){
            res=res*10+(nn-'0');
        }
        return res;
    }
    string numtoss(long long num){
        stack<char>dp;
        string res;
        while(num>0){
            dp.push(num%10+'0');
            num=num/10;
        }
        while(dp.size()>0){
            res+=dp.top();
            dp.pop(); 
        }
        return res;
    }
};
  只要涉及数值运算 都会溢出 那咋办呢?
  一位一位的乘了再加起来 这道题让我们求两个字符串数字的相乘,输入的两个数和返回的数都是以字符串格式储存的,这样做的原因可能是这样可以计算超大数相乘,可以不受 int 或 long 的数值范围的约束,那么该如何来计算乘法呢,小时候都学过多位数的乘法过程,都是每位相乘然后错位相加,那么这里就是用到这种方法,举个例子,比如 89 x 76,那么根据小学的算术知识,不难写出计算过程如下: 
       
8 9  <- num2
7 6  <- num1
-------
    5 4
  4 8
  6 3
5 6
-------
6 7 6 4
  如果自己再写些例子出来,不难发现,两数相乘得到的乘积的长度其实其实不会超过两个数字的长度之和,若 num1 长度为m,num2 长度为n,则 num1 x num2 的长度不会超过 m+n,还有就是要明白乘的时候为什么要错位,比如6乘8得到的 48 为啥要跟6乘9得到的 54 错位相加,因为8是十位上的数字,其本身相当于80,所以错开的一位实际上末尾需要补的0。还有一点需要观察出来的就是,num1 和 num2 中任意位置的两个数字相乘,得到的两位数在最终结果中的位置是确定的,比如 num1 中位置为i的数字乘以 num2 中位置为j的数字,那么得到的两位数字的位置为 i+j 和 i+j+1,明白了这些后,就可以进行错位相加了,累加出最终的结果。
  由于要从个位上开始相乘,所以从 num1 和 num2 字符串的尾部开始往前遍历,分别提取出对应位置上的字符,将其转为整型后相乘。然后确定相乘后的两位数所在的位置 p1 和 p2,由于 p2 相较于 p1 是低位,所以将得到的两位数 mul 先加到 p2 位置上去,这样可能会导致 p2 位上的数字大于9,所以将十位上的数字要加到高位 p1 上去,只将余数留在 p2 位置,这样每个位上的数字都变成一位。然后要做的是从高位开始,将数字存入结果 res 中,记住 leading zeros 要跳过,最后处理下 corner case,即若结果 res 为空,则返回 "0",否则返回结果 res,代码如下:
  
class Solution {
public:
    string multiply(string num1, string num2) {
        int m=num1.size();
        int n=num2.size();
        vector<int>dp(m+n,0);
        string res;
        for(int i=m-1;i>=0;--i){
            for(int j=n-1;j>=0;--j){
                int tmp=(num1[i]-'0')*(num2[j]-'0');
                int p1=i+j,p2=i+j+1;
                int val=dp[p2]+tmp;
                dp[p1]+=val/10;
                dp[p2]=val%10;
            }
        }
        for(auto dd:dp){
            if(!res.empty() || dd!=0){
                res+=(dd+'0'); // 避免了前面是0的元素
            }
        }
        return res.size()>0 ? res:"0";
        
    }
};

 

posted @ 2021-11-19 17:26  aalanwyr  阅读(44)  评论(0编辑  收藏  举报