题目链接

LeetCode

题目描述

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

示例 1:

输入: num1 = “2”, num2 = “3”
输出: “6”

示例 2:

输入: num1 = “123”, num2 = “456”
输出: “56088”

说明:

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

    解题思路

    方法一:模拟竖式乘法

    43. 字符串相乘* - 图1
    1. class Solution {
    2. public String multiply(String num1, String num2) {
    3. // 特殊情况,某个数为0
    4. if(num1.equals("0")||num2.equals("0")){
    5. return "0";
    6. }
    7. String tmp;
    8. String res = "";
    9. // num2从高位到低位,先乘结果*10加后面的结果
    10. for(int i = 0;i<num2.length();++i){
    11. // 当前位和num1相乘
    12. tmp = multi(num1, num2.charAt(i));
    13. // 加上之前的结果
    14. res = add(res,tmp);
    15. }
    16. return res;
    17. }
    18. // 字符串乘法
    19. private String multi(String s,char c){
    20. StringBuilder sb = new StringBuilder();
    21. int tmp;
    22. int x = 0;
    23. for(int i = s.length()-1;i>=0;--i){
    24. tmp = (s.charAt(i)-'0')*(c-'0') + x;
    25. sb.append(tmp%10);
    26. x = tmp/10;
    27. }
    28. if(x!=0){
    29. sb.append(x);
    30. }
    31. return sb.reverse().toString();
    32. }
    33. // 字符串加法
    34. private String add(String s,String c){
    35. StringBuilder sb = new StringBuilder();
    36. // 先把c的最后一位加上,相当于s*10,个位结果是0+c[c.length()-1]
    37. sb.append(c.charAt(c.length()-1));
    38. int tmp;
    39. int x = 0;
    40. int i = s.length()-1,j = c.length()-2;
    41. while(i>=0||j>=0){
    42. int x1 = i>=0? s.charAt(i--) - '0':0;
    43. int x2 = j>=0? c.charAt(j--) - '0':0;
    44. tmp = x1 + x2 + x;
    45. sb.append(tmp%10);
    46. x = tmp/10;
    47. }
    48. if(x!=0){
    49. sb.append(x);
    50. }
    51. return sb.reverse().toString();
    52. }
  • 时间复杂度 O(mn + n^2) m和n分别是num1和num2的长度
  • 空间复杂度 O(m + n)

    方法二:乘法 数组保存

  1. class Solution {
  2. public String multiply(String num1, String num2) {
  3. // 特殊情况,某个数为0
  4. if(num1.equals("0")||num2.equals("0")){
  5. return "0";
  6. }
  7. int m = num1.length(),n = num2.length();
  8. // 两个数相乘 结果长度最大为m+n最小为m+n-1
  9. int[] res = new int[m+n];
  10. for(int i = m - 1;i>=0;--i){
  11. // num1中第i位数和num2中所有数相乘
  12. int x = num1.charAt(i) - '0';
  13. for(int j = n-1;j>=0;--j){
  14. int y = num2.charAt(j) - '0';
  15. // 结果加入相应的位置
  16. // 第一个数对应m+n-1的位置 以此向前移动
  17. res[i+j+1] += x * y;
  18. }
  19. }
  20. // 将各个位置的数分配,使之成为10进制
  21. for(int i = m+n-1;i>0;--i){
  22. res[i-1] += res[i]/10;
  23. res[i] %= 10;
  24. }
  25. // 如果第一位为0 则从第二位开始遍历字符串
  26. int index = res[0] == 0? 1:0;
  27. StringBuilder sb = new StringBuilder();
  28. while(index<m+n){
  29. sb.append(res[index++]);
  30. }
  31. return sb.toString();
  32. }
  33. }
class Solution {
    public String multiply(String num1, String num2) {
        if(num1.length() == 0 || num2.length() == 0){
            return "0";
        }
        char[] arr1 = num1.toCharArray();
        char[] arr2 = num2.toCharArray();
        if(arr1[0] == '0' || arr2[0] == '0'){
            return "0";
        }
        int[] res = new int[arr1.length + arr2.length];
        // 竖式乘法
        for(int x = arr1.length - 1; x >= 0; --x){
            int i = arr1[x] - '0';
            for(int y = arr2.length - 1; y >= 0; --y){
                int j = arr2[y] - '0';
                res[x + y] += (res[x + y + 1] + i * j)/10;
                res[x + y + 1] = (res[x + y + 1] + i * j)%10;
            }
        }
        StringBuilder sb = new StringBuilder();
        int pos = 0;
        if(res[0] == 0){
            ++pos;
        }
        while(pos < res.length){
            sb.append(res[pos++]);
        }
        return sb.toString();
    }
}
  • 时间复杂度 O(mn)
  • 空间复杂度 O(m + n)