数学:43 : Multiply Strings

Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2.

Note:

  1. The length of both num1 and num2 is < 110.
  2. Both num1 and num2 contains only digits 0-9.
  3. Both num1 and num2 does not contain any leading zero.
  4. You must not use any built-in BigInteger library or convert the inputs to integer directly.

字符串相乘问题:博主比较垃圾,长时间不做算法了,抠抠摸摸一个小时写出来下述算法Accepted;

class Solution {
    public String multiply(String num1, String num2) {
        int carry = 0;
        int i = num1.length() - 1;
        int j = num2.length() - 1;
        String result = "";
        String zero = "";
        for(int p = i;p >= 0;p --){
            String tempResult1 = "";
            for(int q = j;q >= 0;q --){
                int temp = ((num1.charAt(p) - 48) * (num2.charAt(q) - 48)) + carry;
                carry = temp / 10;
                int tempResult2 = temp % 10;
                
                tempResult1 = tempResult2 + tempResult1;
                
            }
            if(carry != 0)
                tempResult1 = carry + tempResult1;
            carry = 0;
            tempResult1 += zero;
            result = add(result,tempResult1);
            zero += "0";
        }
        int count = result.length();
        int cut = 0;
        while(result.charAt(cut) == '0' && cut != count - 1)
            cut ++;
        return result.substring(cut);
    }
    public static String add(String num1,String num2){
        String result = "";
        int carry = 0;
        int i = num1.length() - 1,j = num2.length() - 1;
        if(i < j){
            for(int p = i;p < j;p ++)
                num1 = "0" + num1;
        }
        else{
             for(int p = j;p < i;p ++)
                num2 = "0" + num2;
        }
        int num = num1.length() - 1;
        while(num >= 0 ){
            int temp = 0;
            
            temp = num1.charAt(num) - 48 + num2.charAt(num) - 48 + carry;
            
            carry = temp / 10;
            result = (temp % 10) + result;
            
            
            num--;
        }
        if(carry == 1)
            result = '1' + result;
        return result;
    }
    
}
跟手算乘法有些类似。。最后运行时间只有%4.33。。

先贴一种偷懒解法(非算法)

public class Solution   
{  
   public String multiply(String num1, String num2)   
   {  
        BigInteger temp1 = new BigInteger(num1);  
        BigInteger temp2 = new BigInteger(num2);  
        BigInteger result = temp1.multiply(temp2);  
        return result.toString();  
    }  
}  


在网上看到一种很精巧的解法。贴在下面供学习:

       
 1     num1 = new StringBuilder(num1).reverse().toString();
 2     num2 = new StringBuilder(num2).reverse().toString();
 3     // even 99 * 99 is < 10000, so maximaly 4 digits
 4     int[] d = new int[num1.length() + num2.length()];
 5     for (int i = 0; i < num1.length(); i++) {
 6         int a = num1.charAt(i) - '0';
 7         for (int j = 0; j < num2.length(); j++) {
 8             int b = num2.charAt(j) - '0';
 9             d[i + j] += a * b;
10         }
11     }
12     StringBuilder sb = new StringBuilder();
13     for (int i = 0; i < d.length; i++) {
14         int digit = d[i] % 10;
15         int carry = d[i] / 10;
16         sb.insert(0, digit);
17         if (i < d.length - 1)
18             d[i + 1] += carry;
19         }
20     //trim starting zeros
21     while (sb.length() > 0 && sb.charAt(0) == '0') {
22         sb.deleteCharAt(0);
23     }
24     return sb.length() == 0 ? "0" : sb.toString();
25 }

基本思路是将最终结果的每一位都存储到一个一维数组中(为方便起见可以先反转字符串),一维数组长度为m + n或m + n - 1,m和n是两个字符串的长度,所以一维数组长度定义成m + n就够用了。然后5到9行是最精巧的部分,通过双循环将一维数组的每一位都确定(不考虑进位),最后通过遍历数组整理进位(保证每个元素小于10)去除末尾0,合成字符串反转并结束。

这种方法比较容易理解,可是究其根本来说还是有重复的地方。比如一维数组第二位上的数字通过两次运算才得出,第三位大概要经过3次运算(如果m和n都大于3的话)

网上还有一种解法应该是跑的最快,但是不好理解。

    public class Solution   
    {  
        public String multiply(String num1, String num2)  
        {  
            if(num1==null || num2==null)  
                return "";  
            if(num1.charAt(0)=='0')  
                return "0";  
            if(num2.charAt(0)=='0')  
                return "0";  
            int num1length=num1.length();  
            int num2length=num2.length();  
            //分别对两个开始字符串进行转置,便于后面的下标遍历  
            num1=new StringBuilder(num1).reverse().toString();  
            num2=new StringBuilder(num2).reverse().toString();  
            StringBuilder res=new StringBuilder();  
            int jinwei=0;  
            //从低位开始计算,最后乘积的位数为m+n-1,如果进位则是m+n  
            for(int i=0;i<num1length+num2length-1;i++)  
            {  
                int multi=jinwei;  
                for(int j=0;j<=i;j++)  
                {              
                    if(j<num1length && (i-j)<num2length)  
                    {  
                        multi+=(num1.charAt(j)-'0')*(num2.charAt(i-j)-'0');  
                    }  
                }  
                res.append(multi%10);  
                jinwei=multi/10;  
            }  
            //考虑最后一位是否有进位  
            if(jinwei!=0)  
                res.append(jinwei);  
            return res.reverse().toString();       
        }  
    }  
基本思想:反转字符串后从0位到末位一一确定每个位置的值,并立刻处理进位。比如第二位由两个数的1,2位和2,1位相乘相加确定,第三位由两个数1,3位3,1位,2,2位决定。。以此类推,代码比较难理解,但是应该是效率最高的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值