題目
給定兩個整數,被除數 dividend 和除數 divisor。將兩數相除,要求不使用乘法、除法和 mod 運算符。
返回被除數 dividend 除以除數 divisor 得到的商。
示例 1:
輸入: dividend = 10, divisor = 3
輸出: 3
示例 2:
輸入: dividend = 7, divisor = -3
輸出: -2
說明:
被除數和除數均爲 32 位有符號整數。
除數不爲 0。
假設我們的環境只能存儲 32 位有符號整數,其數值範圍是 [−2^31, 2^31 − 1]。本題中,如果除法結果溢出,則返回 231 − 1。
思路
無法使用乘法,只能使用位運算來做
/**
* 解題思路:這題是除法,所以先普及下除法術語
* 商,公式是:(被除數-餘數)÷除數=商,記作:被除數÷除數=商...餘數,是一種數學術語。
* 在一個除法算式裏,被除數、餘數、除數和商的關係爲:(被除數-餘數)÷除數=商,記作:被除數÷除數=商...餘數,
* 進而推導得出:商×除數+餘數=被除數。
*
* 要求商,我們首先想到的是減法,能被減多少次,那麼商就爲多少,但是明顯減法的效率太低
*
* 那麼我們可以用位移法,因爲計算機在做位移時效率特別高,向左移1相當於乘以2,向右位移1相當於除以2
*
* 我們可以把一個dividend(被除數)先除以2^n,n最初爲31,不斷減小n去試探,當某個n滿足dividend/2^n>=divisor時,
*
* 表示我們找到了一個足夠大的數,這個數*divisor是不大於dividend的,所以我們就可以減去2^n個divisor,以此類推
*
* 我們可以以100/3爲例
*
* 2^n是1,2,4,8...2^31這種數,當n爲31時,這個數特別大,100/2^n是一個很小的數,肯定是小於3的,所以循環下來,
*
* 當n=5時,100/32=3, 剛好是大於等於3的,這時我們將100-32*3=4,也就是減去了32個3,接下來我們再處理4,同樣手法可以再減去一個3
*
* 所以一共是減去了33個3,所以商就是33
*
* 這其中得處理一些特殊的數,比如divisor是不能爲0的,Integer.MIN_VALUE和Integer.MAX_VALUE
*
*/
class Solution {
public:
int divide(int dividend, int divisor) {
if(divisor == 0) return 0;
if(divisor == 1) return dividend;
// int溢出的判斷
if(dividend == INT_MIN && divisor == -1) return INT_MAX;
// 兩個數取異或,判斷符號是否相同
bool neg = false;
int res = 0;
if((dividend^divisor) < 0) neg = true;
long a = abs((long)dividend);
long b = abs((long)divisor);
if(a < b) return res;
// 我們可以把一個dividend(被除數)先除以2^n,n最初爲31,不斷減小n去試探
// 當某個n滿足dividend/2^n>=divisor時,表示我們找到了一個足夠大的數
// 這個數*divisor是不大於dividend的,所以我們就可以減去2^n個divisor,以此類推
for(int i = 31;i >= 0;i--){
if((a>>i) >= b){
res += 1<<i;
a -= b<<i;
}
}
return neg? -1*res:res;
}
};