1. 程式人生 > >LeetCode 29——兩數相除

LeetCode 29——兩數相除

urn https 處理 image 循環 繼續 移位操作 div labs

1. 題目

技術分享圖片

2. 解答

2.1. 方法一

題目要求不能使用乘法、除法和除余運算,但我們可以將除法轉移到對數域

$$ \frac{a}{b} = e^{\frac{lna}{lnb}} = e^{lna - lnb}$$

這樣就轉化為指數、對數和減法運算了。因為只能對正整數取對數,因此我們首先要將兩個數都取絕對值,最後再加上符號。

同時,題目要求只能存儲 32 位有符號整數,因此,當數據大於上邊界時,需要進行特殊處理。

class Solution {
public:
     
    int divide(int dividend, int divisor) {
        if(dividend == 0)  return 0;

        double a = fabs(dividend);
        double b = fabs(divisor);
        
        long result = exp(log(a) - log(b));
        
        if ((dividend < 0) ^ (divisor < 0)) result = -result;
        
        if (result > INT_MAX) result = INT_MAX;
        
        return result;
    }
};

2.2. 方法二

利用移位操作。看下面的例子:

$$ 10 \implies 2^1 * 3 + 2^0 * 3 \to \frac{10} {3} = 2^1 + 2^0 = 3$$
$$ 10 \implies 2^2 * 2 + 2^0 * 2 \to \frac{10} {2} = 2^2 + 2^0 = 5$$
$$ 10 \implies 2^3 * 1 + 2^1 * 1 \to \frac{10} {3} = 2^3 + 2^1 = 10$$

我們可以對被除數進行分解。以 10 和 3 為例,首先我們確定 3 的最高次系數,$ 10 > 32^1 $ && $ 10 < 32^2$,因此最高次系數為 2。然後我們用 10 減去 $32^1$,繼續進行剛才的過程,$ 4 > 3

2^0 $ && $ 4 < 3*2^1$,2 的第二高次系數為 1。我們循環進行這個過程,直到最後的數小於除數為止,這些除數前面所有系數的和即為所求。

class Solution {
public:
     
    int divide(int dividend, int divisor) {
  
        long a = labs(dividend); // long 型數據占 8 個字節,labs() 函數對 long 求絕對值
        long b = labs(divisor);
        long temp = b;
        
        long result = 0;
        long cnt = 1;
        
        while (a >= b)
        {
            cnt = 1;
            temp = b;
            while (a >= (temp << 1))
            {
                temp  = temp << 1;
                cnt = cnt << 1; // 表征除數前面的各次系數
            }
            
            a -= temp;
            result += cnt;          
        }
        
        if ((dividend < 0) ^ (divisor < 0)) result = -result;
          
        if (result > INT_MAX) result = INT_MAX; // INT_MAX = 2^32 - 1
        
        return result;*/
    }
};

獲取更多精彩,請關註「seniusen」!
技術分享圖片

LeetCode 29——兩數相除