代码重构:leetcode 29.两数相除

228 阅读1分钟

29.两数相除

本质可以二分,但二分两种。下面展示两种。

同时这题要注意的,也同样是我们大量问题的缩影,如何处理边界问题。如果归纳到我们的解题框架,也就是解题建模:

如何确定我们的答案空间。本题有问题的点在于边界会溢出,也就是Integer.MIN_VALUE/-1会越界。

我们一般考虑除法,都是使用两个正数来除,于是需要使用long来做临时存储。

然后考虑二分时候,有两种思路:

  1. 一种是直接二分求解答案,判断除数*答案是否满足条件。
  2. 利用迭代,我们可以做减法,依次减去2的(0,1,2,....,n)次方,同时依次加入答案,直到最后被减数小于减数

一般第二种更快,第二种的复杂度是o(lg(divdend/divisor))

第一种是o(log(divdend)*32)

第一种:

    public int divide(int div, int divi) {
        long dividend = div, divisor = divi;
        int flag = (dividend ^ divisor) >= 0 ? 1 : -1;
        dividend = Math.abs(dividend);
        divisor = Math.abs(divisor);
        if (divisor > dividend) return 0;
        long left = 0, right = dividend;
        while (left <= right) {
            long mid = left + ((right - left) >> 1);
            long k = mutipK(divisor, mid);
            if (dividend >= k && dividend - k < divisor) {
                if (flag * mid> Integer.MAX_VALUE) return Integer.MAX_VALUE;
                else if (flag * mid < Integer.MIN_VALUE) return Integer.MIN_VALUE;
                else return flag * (int) mid;
            }
            if (k < dividend) left = mid + 1;
            else if (k > dividend) right = mid - 1;
        }
        return 0;
    }

    private long mutipK(long num, long k) {
        long ans = 0;
        for (int i = 0; i < 32; i++) {
            if (((k >> i) & 1) == 1) {
                ans += num;
            }
            num += num;
        }
        return ans;
    }

第二种:

    public int divide(int div, int divi) {
        long dividend = div, divisor = divi;
        int flag = (dividend ^ divisor) >= 0 ? 1 : -1;
        dividend = Math.abs(dividend);
        divisor = Math.abs(divisor);
        if (divisor > dividend) return 0;
        long ans = 0;
        while (dividend>divisor) {
            int t = 1;
            long temp = divisor;
            while (dividend >= temp) {
                dividend -= temp;
                ans += t;
                temp <<= 1;
                t <<= 1;
            }
        }
        if (flag*ans>Integer.MAX_VALUE) return Integer.MAX_VALUE;
        if (flag*ans<Integer.MIN_VALUE) return Integer.MIN_VALUE;
        return flag*(int)ans;
    }