字符串乘法[模拟乘法&加法]

前言

字符串乘法,也即大数相乘,为一道模拟题。此题既考察如何模拟乘?同时考察如何模拟大数加法?除此之外,大数的高位/低位在左边还是右边,这是里面的一处细节,可以延申出很多bug。

一、字符串乘法

在这里插入图片描述

二、乘法&加法的模拟

package everyday.medium;

// 字符串相乘
public class Multiply {
    /*
    字符串相乘,不能直接乘,所以需要进行乘法模拟。
    乘法的步骤:一个数的每一位乘上另一个数,会得到一个数,然后做一个大数加法即可。
    要做大数加法,就得有个整数数组,那么数组的长度是多少呐?
    将最大一位数9放大最大两位数99,即9 * 99 < 10 * 99 = 990;所以两数相乘,必不可能超过两者的长度。
    同理:10 * 100 = 1000,最小也是两者长度-1,即最多包含一个前导0.(除乘0的特殊情况)。
     */
    // review:
    // bug1:对于字符串,从左到右是,先高位再低位,所以做乘法时应该从右往左边遍历。
    // bug2:对于ans数组,从左到右是,先低位再高位,所以转成字符串时应该从右向左遍历。
    // bug3:忽略了+和三元运算符的优先级关系,+ > ?,好久没碰到都忘了,以前错了一次,记忆还是多深刻的。
    // bug4:先低位乘再高位,而字符串是从高位到低位,所以应该倒着来。
    // bug5:第二个数为0,则会出现很多0的情况,提前判断了。
    // 总:两个bug都体现了对细节的把握度不够,没有认真实践去看数字怎么排列,而是好像见过就自以为去了。
    public String multiply(String num1, String num2) {
        int m = num1.length(), n = num2.length();
        int[] ans = new int[m + n];
        // bug5:第二个数为0,则会出现很多0的情况,提前判断了。
        if (num1.length() == 1 && num1.charAt(0) == '0' ||
                num2.length() == 1 && num2.charAt(0) == '0') return "0";
        // bug4:先低位乘再高位,而字符串是从高位到低位,所以应该倒着来。
        for (int i = num1.length() - 1; i >= 0; i--) {
            int k = num1.charAt(i) - '0';
            if (k == 0) continue;

            String s = multiply(k, num2);
            add(s, num1.length() - 1 - i, ans);
        }
        StringBuilder sb = new StringBuilder();
        // bug2:结果从左到右是高位到低位,弄反了。
        for (int i = ans.length - 1; i >= 0; i--) {
            if (i == ans.length - 1 && ans[i] == 0) continue;
            sb.append(ans[i]);
        }
        return sb.toString();
    }

    private void add(String s, int offset, int[] ans) {
        int plus = 0;
        for (int i = offset; i < ans.length; i++) {
            // bug3:忽略了+和三元运算符的优先级关系,+ > ?
            int val = ans[i] + (i - offset < s.length() ? s.charAt(i - offset) - '0' : 0) + plus;

            ans[i] = val % 10;
            plus = val / 10;
        }
    }

    private String multiply(int m, String s) {
        int plus = 0;
        StringBuilder sb = new StringBuilder();
        // bug1:注意模拟时,先低位再高位。
        for (int i = s.length() - 1; i >= 0; i--) {
            int val = (s.charAt(i) - '0') * m + plus;

            plus = val / 10;
            sb.append(val - plus * 10);
        }
        if (plus != 0) sb.append(plus);
        return sb.toString();
    }

    public static void main(String[] args) {
        new Multiply().multiply("123", "456");
    }
}

总结

1)大数乘法,同时考察字符串的乘法&字符串的加法。

2)对于模拟数乘/数加,细节的本质在于高位/低位是在左还是在右,如果不细心校验,这可以引出很多bug。

参考文献

[1] LeetCode 字符串乘法

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值