字符串相乘,模拟乘法

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

示例 1:

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

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

这个很简单,只要按照平常的算法来写就行。其实这道题是典型的复杂问题分解简单问题的思路。首先是一个字符和字符串的乘法,然后是字符串的加法。最后是去掉前导0。写出来只是时间问题。

class Solution {
  public String multiply(String num1, String num2) {
    int num1Len = num1.length();
    int num2Len = num2.length();

    StringBuilder lastZero = new StringBuilder();
    List<String> totalNum = new ArrayList<>();
    for (int i = num1Len - 1; i > -1; --i) {
      int carry = 0;
      StringBuilder sb = new StringBuilder();
      sb.append(lastZero);
      for (int j = num2Len - 1; j > -1; --j) {    
        char num1CurCh = num1.charAt(i);
        if (num1CurCh == '0') {
            sb.append("0");
            break;
        }

        char num2CurCh = num2.charAt(j);
        int temp = (num1CurCh - '0') * (num2CurCh - '0') + carry;
        if (temp > 9) {
          sb.insert(0, temp % 10);
          carry = temp / 10;
        } else {
          sb.insert(0, temp);
          carry = 0;
        }
      }
      if (carry != 0) {
        sb.insert(0, carry);
      }

      lastZero.append("0");
      totalNum.add(sb.toString());
    }

    String ret = "";
    for (String num : totalNum) {
      ret = plusStr(ret, num);
    }

    // 去掉前导0
    int idx;
    for (idx = 0; idx < ret.length(); ++idx) {
        if (ret.charAt(idx) != '0') {
            break;
        }
    }
    if (idx == ret.length()) {
        ret = "0";
    } else {
        ret = ret.substring(idx);
    }

    return ret;
  }

  public String plusStr(String s1, String s2) {
    if (s1.length() < s2.length()) {
      return plusStr(s2, s1);
    }

    int s1Len = s1.length();
    int subVal = s1Len - s2.length();
    int carry = 0;
    StringBuilder sb = new StringBuilder();
    for (int i = s1Len - 1; i > -1; --i) {
      char s1CurCh = s1.charAt(i);
      if (i - subVal >= 0) {
        char s2CurCh = s2.charAt(i - subVal);
        int temp = Integer.parseInt(s1CurCh + "") + Integer.parseInt(s2CurCh + "") + carry;
        if (temp > 9) {
          sb.insert(0, temp % 10);
          carry = temp / 10;
        } else {
          sb.insert(0, temp);
          carry = 0;
        }
      } else {
        if (carry != 0) {
          int temp = Integer.parseInt(s1CurCh + "") + carry;
          if (temp > 9) {
            sb.insert(0, temp % 10);
            carry = temp / 10;
          } else {
            sb.insert(0, temp);
            carry = 0;
          }
        } else {
          sb.insert(0, s1.substring(0, i + 1));
          break;
        }
      }
    }
    if (carry != 0) {
      sb.insert(0, carry);
    }

    return sb.toString();
  }
}

上面的写法比较垃圾,下面C++写法才是神啊!

class Solution {
public:
    string multiply(string num1, string num2) {
        int n1 = num1.size(), n2 = num2.size();
        string ans(n1 + n2, '0');
        
        for(int i = n1 - 1; i >= 0; i--) {
        	for(int j = n2 - 1; j >= 0; j--) {
        		int temp = (ans[i + j + 1] - '0') + (num1[i] - '0') * (num2[j] - '0');
        		ans[i + j + 1] = temp % 10 + '0';
        		ans[i + j] += temp / 10;
        	}
        }
        
        for(int i = 0; i < n1 + n2; i++) {
        	if (ans[i] != '0') return ans.substr(i);
        }
        
        return "0";		
    }
    
	string Plus(string s1, string s2) {
		int remain = 0;
		int s1Idx = s1.length() - 1;
		int s2Idx = s2.length() - 1;
		string ret = "";
		do {
			int s1Num = s1Idx >= 0 ? s1[s1Idx] - '0' : 0;
			int s2Num = s2Idx >= 0 ? s2[s2Idx] - '0' : 0;
			int sum = s1Num + s2Num + remain;
			ret.insert(0, to_string(sum % 10));
			remain = sum / 10;
			--s1Idx;
			--s2Idx;
		} while (remain != 0 || (s1Idx >= 0 && s2Idx >= 0));
		
		if (s1Idx >= 0) {
			ret.insert(0, s1.substr(0, s1Idx + 1));
		}
		
		if (s2Idx >= 0) {
			ret.insert(0, s2.substr(0, s2Idx + 1));
		}
		
		return ret;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值