Multiply Strings

51 篇文章 0 订阅
35 篇文章 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.


思路 1 : 这道题属于数值操作的题目,其实更多地是考察乘法运算的本质。基本思路是和加法运算还是近似的,只是进位和结果长度复杂一些。我们仍然是从低位到高位对每一位进行计算,假设第一个数长度是n,第二个数长度是m,我们知道结果长度为m+n或者m+n-1(没有进位的情况)。对于某一位i,要计算这个位上的数字,我们需要对所有能组合出这一位结果的位进行乘法,即第1位和第i-1位,第2位和第i-2位,... ,然后累加起来,最后我们取个位上的数值,然后剩下的作为进位放到下一轮循环中。这个算法两层循环,每层循环次数是O(m+n),所以时间复杂度是O((m+n)^2)。算法中不需要额外空间,只需要维护一个进位变量即可,所以空间复杂度是O(1)。

实现中有两个小细节,一个是循环中最后有一个if判断,其实就是看最高一位是不是0(最高第二位不可能是0,除非两个源字符串最高位带有0),如果是就不需要加入字符串中了。另一个小问题是我们是由低位到高位放入结果串的,所以最后要进行一次reverse,因为是一个O(m+n)的操作,不会影响算法复杂度。

这道题其实还有更加优的做法,就是用十大最牛的算法之一--Fast Fourier transform(FFT)。使用FFT可以在O(nlogn)时间内求出多项式的乘法,在这里只需要把变量x带入10,然后按照求多项式的方法就可以求出两个大整数的成绩了。想了解细节的朋友搜一下快速傅里叶变换求多项式乘积就可以找到相关资料了,是比较成熟的算法。不过FFT实现不是很简单,所以在面试中一般不需要写代码,只需要知道这个思路和基本工作原理就可以了哈。


思路 2 :其实理解起来很简单, 首先将 两个 string reverse, 这样最终结果的  digits[i + j] += num1[i] * num2[j]  ,  最后把 大于 9的进位就行了。

易错点: 1, 注意 俩数有个 0 的情况,  2, 最后结果 首字母为0 的情况,  3, stringbuilder 删除某一位 用的  deleteCharAt(i)  而不是 remove(i)


public class Solution {
    public String multiply(String num1, String num2) {
    if(num1 == null || num2 == null || num1.length()==0 || num2.length()==0)
        return "";
    if(num1.charAt(0)=='0')
        return "0";
    if(num2.charAt(0)=='0')
        return "0";
    StringBuilder res = new StringBuilder();
    int num = 0;
    for(int i=num1.length()+num2.length();i>0;i--)//----代表第 i 位。
    {
        for(int j=Math.min(i-1,num1.length());j>0;j--)//----
        {
            if(i-j<=num2.length())//---
            {
                num += (int)(num1.charAt(j-1)-'0')*(int)(num2.charAt(i-1-j)-'0'); // (j - 1)  +  (i - 1 - j) = i  
            }
        }
        if(i!=1 || num>0)//---
            res.append(num%10);
        num = num/10;//---
    }
    return res.reverse().toString();
}
}

public class Solution {
    public String multiply(String num1, String num2) {
        if(num1 == null || num2 == null || num1.length() < 1 || num2.length() < 1)
            return null;
        if(num1.charAt(0) == '0' || num2.charAt(0) == '0'){
            return "0";
        }
        StringBuilder sb1 = (new StringBuilder(num1)).reverse();
        StringBuilder sb2 = (new StringBuilder(num2)).reverse();
        int[] digits = new int[num1.length() + num2.length()];
        for(int i = 0; i < num1.length(); i++){
            for(int j = 0; j < num2.length(); j++){
                digits[i + j] += (sb1.charAt(i) - '0') * (sb2.charAt(j) - '0');//----
            }
        }
        
        int carry = 0;
        StringBuilder ret = new StringBuilder();
        for(int i = 0; i < digits.length; i++){
            int digit = carry + digits[i];
            ret.append(digit % 10);
            carry = digit / 10;
        }
        if(carry > 0){
            ret.append(carry);
        }
        if(ret.charAt(ret.length() - 1) == '0')
            ret.deleteCharAt(ret.length() - 1);//----
        return ret.reverse().toString();
    }
}

public class Solution {
    public String multiply(String num1, String num2) {
        if(num1.length() < 1 || num2.length() < 1)
            return null;
        if(num1.charAt(0) == '0' || num2.charAt(0) == '0')
            return "0";
        int[] int1Arr = new int[num1.length()];
        int[] int2Arr = new int[num2.length()];
        int[] resultArr = new int[num1.length() + num2.length()];
        
        //Copy and reverse the string num to integer array
        for(int i = 0; i < num1.length(); i++){
            int1Arr[i] = num1.charAt(num1.length() - 1 - i) - '0';
        }
        for(int i = 0; i < num2.length(); i++){
            int2Arr[i] = num2.charAt(num2.length() - 1 - i) - '0';
        }
        
        //Mutiply the numbers from int1Arr and int2Arr, but in every digit the number may larger than 10
        
        for(int i = 0; i < num1.length(); i++){
            for(int j = 0; j < num2.length(); j++){
                resultArr[i + j] += int1Arr[i] * int2Arr[j];
            }
        }
        
        // Carry carrier if the number in one digit larger than 10
        
        int carrier = 0;
        for(int i = 0; i < resultArr.length; i++){
            int digit = (resultArr[i] + carrier) % 10;
            carrier = (resultArr[i] + carrier) / 10;
            resultArr[i] = digit;
        }
        
        //Copy the number from integer array to StringBuilder
        StringBuilder sb = new StringBuilder();
        for(int i : resultArr)
            sb.append(i);
        sb = sb.reverse();
        //If the first digit is 0 , it is useless digit.
        if(sb.charAt(0) == '0'){
            return sb.substring(1, sb.length());
        }
        return sb.toString();
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值