[LeetCode]29 兩數相除和一個小坑點

給定兩個整數,被除數 dividend 和除數 divisor。將兩數相除,要求不使用乘法、除法和 mod 運算符。

返回被除數 dividend 除以除數 divisor 得到的商。

示例 1:

輸入: dividend = 10, divisor = 3
輸出: 3
示例 2:

輸入: dividend = 7, divisor = -3
輸出: -2
說明:

被除數和除數均爲 32 位有符號整數。
除數不爲 0。
假設我們的環境只能存儲 32 位有符號整數,其數值範圍是 [−231,  231 − 1]。本題中,如果除法結果溢出,則返回 231 − 1。

  

思路一:

就是小學時候還沒學除法的時候用的辦法,用被減數去重複減去減數,但是毫無疑問這種辦法效率並不高。如果其中一個Integer.MAX_VALUE

另一個是1,就得循環那麼多次,顯然這不是做這個的好的解決辦法。

思路二:

那麼除了一個個將還有什麼效率好的辦法呢,我開始也想用移位,但是還是沒能想出來,畢竟太菜。

因爲dividend即被減數規定了範圍,那麼能夠被減數能整除的最大整數就是2的31次方,那麼,從2的31依次開始試探,試探數之間的關係就是二倍關係。二倍關係就跟移位操作掛上夠了,左移相當於X2,右移相當於/2,如果被除數/2^i(i=31,30...1,0)的商是大於除數的,則本題答案可以加上此時的2^i,同時,將被減數減去2^i,當然,在此之前,爲了避免兩個數異號而帶來的不便,事先將兩個數字做一下絕對值處理就好了。

然後根據這條思路寫出瞭如下代碼:

class Solution {
    public int divide(int dividend, int divisor) {
         boolean is = false;
        int res = 0;
        if(dividend==0)
            return 0;
        if(divisor==1)
            return dividend;
        if(dividend==Integer.MIN_VALUE&&divisor==-1)
            return Integer.MAX_VALUE;
        if((dividend<0&&divisor>0)||(dividend>0&&divisor<0))
            is = true;//如果異號
        long divd = Math.abs(dividend);
        long divs = Math.abs(divisor);
        for(int i = 31;i>=0;i--){
            if((divd>>i)>=divs){
                res+=1<<i;
                divd-=divs<<i;
            }
        }
        return is?-res:res;//異號結果變負
    }
}
View Code

測幾個用例,誒好像沒問題。提交,WA(哭)

輸入:
-2147483648
2
輸出:
0
預期:
-1073741824

  

一時半會沒想通,直到看見Math.abs()的源代碼:

  /**
     * Returns the absolute value of an {@code int} value.
     * If the argument is not negative, the argument is returned.
     * If the argument is negative, the negation of the argument is returned.
     *
     * <p>Note that if the argument is equal to the value of
     * {@link Integer#MIN_VALUE}, the most negative representable
     * {@code int} value, the result is that same value, which is
     * negative.
     *
     * @param   a   the argument whose absolute value is to be determined
     * @return  the absolute value of the argument.
     */
    public static int abs(int a) {
        return (a < 0) ? -a : a;
    }

  

如果是Integer.MIN_VALUE,不返回絕對值,返回本身。。所以這裏算是一個小坑點了,做法就是,將int轉化爲long來去絕對值(因爲本題規定了被除數範圍,如果沒有規定,強制轉爲long也可能沒用。。)

最後的AC代碼:

class Solution {
    public int divide(int dividend, int divisor) {
         boolean is = false;
        int res = 0;
        if(dividend==0)
            return 0;
        if(divisor==1)
            return dividend;
        if(dividend==Integer.MIN_VALUE&&divisor==-1)
            return Integer.MAX_VALUE;
        if((dividend<0&&divisor>0)||(dividend>0&&divisor<0))
            is = true;//如果異號
        long divd = Math.abs((long)(dividend));
        long divs = Math.abs((long)(divisor));
        for(int i = 31;i>=0;i--){
            if((divd>>i)>=divs){
                res+=1<<i;
                divd-=divs<<i;
            }
        }
        return is?-res:res;//異號結果變負
    }
}
View Code

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章