力扣一题 43. 字符串相乘

558 阅读2分钟

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

image-20211103131526913.png

分析

本题难度为中等,题目中已经限制了不能使用大数或者直接将字符串转换为整数来处理,那么显然我们只能采用“逐位相乘,并保存每位的结果和进制”这种方法来计算

方法一

原理如下,让52从尾开始,逐位与34相乘,得到每一位与34相乘的结果,并将这些结果加起来即得到答案。由于不能直接将string转化为数值计算,所以我们需要使用StringBuilder来保存每一位相乘的结果,并在计算前进行补0的操作

image-20211103132644464.png

代码

class Solution {
    public String multiply(String num1, String num2) {
        // 其中一个数为0,直接返回结果
        if(num1.equals("0")||num2.equals("0")) return "0";
        char[]arr1=num1.toCharArray();
        char[]arr2=num2.toCharArray();
        StringBuilder sb=null;
        String res="";
        for(int i=arr2.length-1;i>=0;i--){
            int carry=0;
            // 转化为整数
            int b=arr2[i]-'0';
            sb=new StringBuilder();
            int k=arr2.length-1-i;
            // 补充尾部的0
            while(k-->0) sb.append(0);
            for(int j=arr1.length-1;j>=0;j--){
                int a=arr1[j]-'0';
                carry+=a*b;
                sb.append(carry%10);
                carry/=10;
            }
            if(carry!=0) sb.append(carry);
            // 将得到的结果相加
            res=stringAdd(res,sb.reverse().toString());
        }
        return res;
    }
​
    String stringAdd(String s1,String s2){
        if(s1.equals("")) return s2;
        if(s2.equals("")) return s1;
        char[]arr1=s1.toCharArray();
        char[]arr2=s2.toCharArray();
        StringBuilder sb=new StringBuilder();
        int carry=0;
        int i=arr1.length-1,j=arr2.length-1;
        while(i>=0||j>=0||carry==1){
            carry+=i>=0?arr1[i--]-'0':0;
            carry+=j>=0?arr2[j--]-'0':0;
            sb.append(carry%10);
            carry/=10;
        }
        return sb.reverse().toString();
    }
}

方法二

方法一需要重复地进行字符与整数的转换,整个过程效率较低,根本原因就是采用了字符串来记录中间计算的结果,所以我们可以进行优化。按照方法一的思路 ,我们可以采用数组来记录计算的中间结果,这样在进行中间结果的相加时,直接将数组相应位上的数组进行相加即可,不需要像方法一那样将字符转化为整数,整数相加之后在转化为字符串。

关于数组的大小:因为两数相乘,结果的位数最大等于两位的位数之和,所以数组的大小设置为n1+n2即可

代码

class Solution {
    public String multiply(String num1, String num2) {
        if(num1.equals("0")||num2.equals("0")) return "0";
        int n1=num1.length(),n2=num2.length();
        int []arr=new int[n1+n2];
        char[]arr1=num1.toCharArray();
        char[]arr2=num2.toCharArray();
        for(int i=n1-1;i>=0;i--){
            int a=arr1[i]-'0';
            for(int j=n2-1;j>=0;j--){
                int sum=0;
                int b=arr2[j]-'0';
                // 得到的结果的个数部分加上该位本来的值
                sum=a*b+arr[i+j+1];
                arr[i+j+1]=sum%10;
                arr[i+j]+=sum/10;
            }
        }
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<arr.length;i++){
            // 去除首位的0
            if(i==0&&arr[i]==0) continue;
            sb.append(arr[i]);
        }
        return sb.toString();
    }
}