两数相除
题目:

思路:
【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; } }

浙公网安备 33010602011771号