LeetCode第[29]题(Java):Divide Two Integers

题目:两整数相除

难度:Medium

题目内容

Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator.

Return the quotient after dividing dividend by divisor.

The integer division should truncate toward zero.

翻译

给定两个整数,被除数和除数,不使用乘法,除法和mod运算符。

在除以除数后,返回商数。

整数除法应该截断为零。

Example 1:

Input: dividend = 10, divisor = 3
Output: 3

Example 2:

Input: dividend = 7, divisor = -3
Output: -2

我的思路:因为此题需要考虑的边界情况太多,而重点考察的却不是这些,故只做算法分析,不求跑通所有代码。

    最笨的方法:直接循环减去除数。。。

    方法二:之前印象中好像在哪见过,每次循环都减去能减的最大的除数*2^n,并且每次循环把2次幂都加起来。商就是这些2次幂的和。

举个例子:20/3,

  第一次循环,20>3*1,20>3*2,20>3*2*2,已经最大,打住, dividend=20-3*2*2=8, ans = 2*2 = 4

  第二次循环,8>3*1,8>3*2,已经最大,打住, dividend=8-3*2=2, ans = 4 + 2 = 6

  dividend < 3 退出循环,最后 ans = 6

MyCode

 1     public int divide(int dividend, int divisor) {
 2         if (dividend != 0 && dividend  == -dividend && divisor == -1) {
 3             return -(dividend+1);
 4         }
 5         return div(dividend, divisor);
 6     }
 7     public static int div(int x, int y) {
 8         int tag = 1;
 9         if ((x ^ y) < 0) { // 位运算符优先级很低,记得加括号
10             tag = -1;
11             if (x < 0) {
12                 x = -x;
13             } else {
14                 y = -y;
15             }
16         } else if (x < 0) {
17             x = -x;
18             y = -y;
19         } // 都设置成正整数
20         int ans = 0;
21         while (x >= y) {
22             int flag = 1;
23             while ((x >> 1) >= y * flag) {  // 如果使用x >= y * (flag << 1) 则有可能溢出
24                 flag <<= 1;
25             }
26             x -= y*flag;
27             ans += flag;
28         }
29         return ans*tag;
30     }

编码过程中出现问题

1、bad operand types for binary operator “^”    

  ————位运算符的优先级很低,甚至比==都要低,所以遇见位运算符要记得加括号

2、溢出

  ————在23行处,进行了>>1(乘以2)的判断运算,此时可能溢出,所以在进行判断运算时,即先运算再判断是否能如此运算的时候,应该将判断符(==、>=等)两边的运算符平衡一下,如果一边可能溢出,则将此运算符移至另一边。【此处与之前的leetCode的某一题貌似是 数字反转 很像】

答案代码

 1    public int divide(int dividend, int divisor) {
 2         if(dividend<<1 == 0 && divisor == -1){// x /y = -2^32 / -1, overflow
 3             return (-1) >>> 1;
 4         }
 5         
 6         if(divisor == 1 || dividend == 0){ // x / y = x / 1 or 0 / y
 7             return dividend;
 8         }
 9         if(divisor == dividend) return 1; // x / y when x == y
10         else if(divisor<<1 == 0) return 0; // x / y  = x / (-2^32)
11        
12         int sign; //sign
13         if(divisor < 0 && dividend < 0 || divisor > 0 && dividend > 0){
14             sign = 1;
15         }else{
16             sign = -1;
17         }
18         
19         divisor = divisor < 0 ? -divisor : divisor; // positive divisor
20         int left = dividend, res = 0;
21         if(dividend << 1 == 0){    // if x / y = (-2^32) / y, first we add x by y, then -x will not overflow
22             left += divisor;
23             res++;
24         }
25         left = left > 0 ? left : -left;
26         
27         int tDivisor = divisor, tA = 1;
28         while(left >= divisor){
29             tDivisor = divisor;
30             tA = 1;
31             while(tDivisor << 1 > 0 && left >= tDivisor << 1){ // max tDivisor = tA * divisor <= left
32                 tDivisor <<= 1;
33                 tA <<= 1;
34             }
35             res += tA;
36             left -= tDivisor;
37         }
38         return sign == 1 ? res : -res;  
39     }

其实真正的代码从27行开始,和我代码是一个意思,不过前面多出了很多处理边界的情况,在此不做讨论。

另外一种方法——二分法

和朋友讨论发现另外一种巧妙地解法,用二分法:

 1     public static int div2(int x, int y) {
 2         int tag = 1;
 3         if ((x ^ y) < 0) { // 位运算符优先级很低,记得加括号
 4             tag = -1;
 5             if (x < 0) {
 6                 x = -x;
 7             } else {
 8                 y = -y;
 9             }
10         } else if (x < 0) {
11             x = -x;
12             y = -y;
13         }
14         int ans = 0;  // 算法从此处开始
15         int low = 1;
16         int high = x;
17         while (low <= high) {
18             int mid = low + ((high-low)>>1);
19             int rest = x - y*mid;
20             System.out.println(rest);
21             if (rest >= 0 && rest < y) {
22                 ans = mid;
23                 break;
24             }
25             if (rest < 0) {
26                 high = mid - 1;
27             } else if (rest >= y) {
28                 low = mid + 1;
29             }
30         }
31         return ans * tag;
32     } 

猜你喜欢

转载自www.cnblogs.com/Xieyang-blog/p/8984584.html
今日推荐