两数相除

题目:

思路:

【1】从数学角度上来说,除法本质上就是可以转化为减法的,如10/3,本质上就是找出10最多能减去多少个3【这是编程思维,在java中/是不保留小数的】,所以简单的可以转化为循环遍历的减法【暴力破解的方式】

【2】当然基于暴力破解的思路,要做的便是简化循环,那么可以在循环中每次都先找到最大除数【利用位移,即乘2的方式,进行倍增,减少循环的次数】,如100/3,第一次最大除数为96【3*2^5】,余数为4,第二次最大除数为3,余1。即总次数为2+5=7,远比暴力的33次循环来的少。

【3】当然基于二分的方式又可以演化成一种时间复杂度为O(1)的方式,就是利用位移,因为int是32位,第一位用于标记符号,所以循环31次,从大到小循环。这种不一定会比上面那种快,因为不管怎么样每次都是要循环31次,有可能会做无用功,而且平均下来的时间不一定会比上面少。

代码展示:

基于暴力破解的思想做的:

//执行用时:2739 ms, 在所有 Java 提交中击败了5.03%的用户
//内存消耗:38.9 MB, 在所有 Java 提交中击败了48.99%的用户
class Solution {
    public int divide(int dividend, int divisor) {
        //特殊情况处理
        if (dividend == 0 || divisor == 1){
            return dividend;
        }else if(divisor == -1){
            //溢出的情况
            return dividend == Integer.MIN_VALUE ? Integer.MAX_VALUE : -dividend;
        }else if (divisor == Integer.MIN_VALUE){
            return dividend == Integer.MIN_VALUE ? 1 : 0;
        }
        //符号相不相同
        boolean isNeg = false;
        //为什么采用负数是因为最小为-2147483648,转成正数会出现越界
        if (dividend > 0) {
            dividend = -dividend;
            isNeg = true;
        }
        if (divisor > 0) {
            divisor = -divisor;
            isNeg = !isNeg;
        }
        int result = 0;
        while (dividend <= divisor){
            dividend -= divisor;
            result++;
        }
        return isNeg ? -result : result;
    }
}

基于暴力思想上采用二分进行优化:

//执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
//内存消耗:38.7 MB, 在所有 Java 提交中击败了76.01%的用户
class Solution {
    public int divide(int dividend, int divisor) {
        //特殊情况处理
        if (dividend == 0 || divisor == 1){
            return dividend;
        }else if(divisor == -1){
            //溢出的情况
            return dividend == Integer.MIN_VALUE ? Integer.MAX_VALUE : -dividend;
        }else if (divisor == Integer.MIN_VALUE){
            return dividend == Integer.MIN_VALUE ? 1 : 0;
        }
        //符号相不相同
        boolean isNeg = false;
        //为什么采用负数是因为最小为-2147483648,转成正数会出现越界
        if (dividend > 0) {
            dividend = -dividend;
            isNeg = true;
        }
        if (divisor > 0) {
            divisor = -divisor;
            isNeg = !isNeg;
        }
        int result = 0;
        while (dividend <= divisor){
            int temp = divisor,c = 1;
            //尽可能每次都找出最大的除数
            while (dividend - temp <= temp) {
                temp = temp << 1;
                c = c << 1;
            }
            dividend -= temp;
            result += c;
        }
        return !isNeg ? result : -result;
    }
}

 时间复杂度为O(1)的做法:

//执行用时:1 ms, 在所有 Java 提交中击败了76.03%的用户
//内存消耗:39 MB, 在所有 Java 提交中击败了29.06%的用户
class Solution {
    public int divide(int dividend, int divisor) {
        //特殊情况处理
        if (dividend == 0 || divisor == 1){
            return dividend;
        }else if(divisor == -1){
            //溢出的情况
            return dividend == Integer.MIN_VALUE ? Integer.MAX_VALUE : -dividend;
        }else if (divisor == Integer.MIN_VALUE){
            return dividend == Integer.MIN_VALUE ? 1 : 0;
        }
        int result = 0;
        //符号相不相同
        boolean isNeg = (dividend ^ divisor) < 0;
        //基于-2147483648的特殊处理,相当于提前取出了一次
        if(dividend == Integer.MIN_VALUE) {
            dividend += Math.abs(divisor);
            result++;
        }
        dividend = Math.abs(dividend);
        divisor =  Math.abs(divisor);

        for(int i = 31; i >= 0; i--) {
            if((dividend >> i) >= divisor ) {
                result += 1 << i;
                dividend -= divisor << i;
            }
        }
        return !isNeg ? result : -result;
    }
}

 

posted @ 2023-01-11 14:19  忧愁的chafry  阅读(674)  评论(0)    收藏  举报