LeetCode 43. 字符串相乘 **

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

示例 1:

测试用例

示例:

输入: num1 = “3”, num2 = “4”
输出: “12”

说明:

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

解题思路

乘法
令 m 和 n 分别表示 num1 和num2 的长度,并且它们均不为 0,则 num1 和 num2 的乘积的长度为 m + n − 1 m+n−1 m+n1 m + n m+n m+n。简单证明如下:

  • 如果 n u m 1 num_1 num1 n u m 2 num_2 num2 都取最小值,则 n u m 1 = 1 0 m − 1 num_1 =10^{m-1} num1=10m1 n u m 2 = 1 0 n − 1 num_2 =10^{n-1} num2=10n1 n u m 1 ∗ n u m 2 = 1 0 m + n − 2 num_1*num_2=10^{m+n-2} num1num2=10m+n2。乘积的长度为 m + n − 1 m + n −1 m+n1
  • 如果 n u m 1 num1 num1 n u m 2 num2 num2 都取最大值,则 n u m 1 = 1 0 m − 1 num_1 =10^m-1 num1=10m1 n u m 2 = 1 0 n − 1 num_2 =10^n-1 num2=10n1 n u m 1 ∗ n u m 2 = 1 0 m + n − 1 0 m − 1 0 n + 1 num_1 *num_2=10^{m+n}-10^m-10^n+1 num1num2=10m+n10m10n+1。乘积显然小于 1 0 m + n 10^{m+n} 10m+n且大于 1 0 m + n − 1 10^{m+n-1} 10m+n1,因此乘积的长度为 m + n m+n m+n

由于 n u m 1 num1 num1 n u m 2 num2 num2 的乘积的最大长度为 m + n m+n m+n,因此创建长度为 m + n m+n m+n 的数组 a r r arr arr 用于存储乘积。对于任意 0 ≤ i < m 0≤i<m 0i<m 0 ≤ j < n 0≤j<n 0j<n n u m 1 [ i ] ∗ n u m 2 [ j ] num_1[i]*num_2[j] num1[i]num2[j] 的结果位于 a r r [ i + j + 1 ] arr[i+j+1] arr[i+j+1],如果 a r r [ i + j + 1 ] ≥ 10 arr[i+j+1]≥10 arr[i+j+1]10,则将进位部分加到 a r r [ i + j ] arr[i+j] arr[i+j]

最后,将数组 a r r arr arr 转成字符串,如果最高位是 0 则舍弃最高位。

Code

class Solution {
    
    
    public String multiply(String num1, String num2) {
    
    
        if (num1.equals("0") || num2.equals("0")) {
    
    
            return "0";
        }
        int m = num1.length(), n = num2.length();
        int[] arr = new int[m + n];
        for (int i = m - 1; i >= 0 ; i--) {
    
    
            int x = num1.charAt(i) - '0';
            for (int j = n - 1; j >= 0; j--) {
    
    
                int y = num2.charAt(j) - '0';
                arr[i + j + 1] += x * y;
            }
        }
        for (int i = m + n - 1; i > 0 ; i--) {
    
    
            arr[i - 1] += arr[i] / 10;
            arr[i] = arr[i] % 10;
        }
        int index = arr[0] == 0 ? 1 : 0;
        StringBuffer str =new StringBuffer();
        while (index < m + n){
    
    
            str.append(arr[index]);
            index++;
        }
        return str.toString();
    }
}

复杂度分析

  • 时间复杂度 O ( m n ) O(mn) O(mn),其中 m 和 n 分别是 n u m 1 num_1 num1 n u m 2 num_2 num2 的长度。需要计算 n u m 1 num_1 num1的每一位和 n u m 2 num_2 num2 的每一位的乘积。

  • 空间复杂度 O ( m + n ) O(m+n) O(m+n),其中 m 和 n 分别是 n u m 1 num_1 num1 n u m 2 num_2 num2 的长度。需要创建一个长度为 m + n m+n m+n 的数组存储乘积。

解法2

模拟「竖式乘法」的方法计算乘积
Demo

class Solution {
    
    
    //string multiply
    public String multiply(String num1, String num2) {
    
    
        if (num1.equals("0") || num2.equals("0"))
            return "0";
        String result = "0";
        int m = num1.length(), n = num2.length();
        for (int i = n - 1; i >= 0; i--) {
    
    
            int e2 = num2.charAt(i) - '0';
            StringBuffer str = new StringBuffer();
            //补零
            for (int p = 0; p < n - 1 - i; p++) {
    
    
                str.append("0");
            }
            int carry = 0;
            for (int j = m - 1; j >= 0 || carry != 0; j--) {
    
    
                int e1 =  j < 0 ? 0 : num1.charAt(j) - '0';
                int temp = e1 * e2 + carry;
                str.append(temp % 10);
                carry = temp / 10;
            }
            result = addStrings(result, str.reverse().toString());
        }
        return result;
    }
    //string sum
    public String addStrings(String num1, String num2) {
    
    
        int m = num1.length(), n = num2.length(), carry = 0;
        StringBuffer answer = new StringBuffer();
        while (m > 0 || n > 0 || carry != 0) {
    
    
            int x = m > 0 ? num1.charAt(m - 1) - '0' : 0;
            int y = n > 0 ? num2.charAt(n - 1) - '0' : 0;
            int temp = x + y + carry;
            answer.append(temp % 10);
            carry = temp / 10;
            m--;
            n--;
        }
        return answer.reverse().toString();

    }
}

复杂度

猜你喜欢

转载自blog.csdn.net/weixin_43405220/article/details/108012731