1. 程式人生 > 其它 >LeetCode-29 兩數相除

LeetCode-29 兩數相除

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/divide-two-integers

題目描述

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

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

整數除法的結果應當截去(truncate)其小數部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2

 

示例 1:

輸入: dividend = 10, divisor = 3
輸出: 3
解釋: 10/3 = truncate(3.33333..) = truncate(3) = 3
示例 2:

輸入: dividend = 7, divisor = -3
輸出: -2
解釋: 7/-3 = truncate(-2.33333..) = -2
 

提示:

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

 

解題思路

很有價值的一道題,由於限制了不能使用long 和除法,需要考慮各種邊界問題和使用減法或者位運算來代替。

首先判斷邊界,已知除數不為0:

在被除數等於-231時,如果除數是1,則返回-231,如果除數是-1則返回溢位,也就是231-1。

如果除數是-231

判斷被除數是否為-231如果是,則返回1,如果不是則返回0。

被除數是0時,返回0。

然後解決符號的問題,如果兩數同號為正異號為負,並且int中負數域比正數大,可以避免溢位,所以全部轉換為負數,最後再根據原始符號的結果重新賦符號

最暴力的想法是將被除數不斷的減去除數並且計數,計數就是商,不出所料的超時了。

採用快速加法的思想,建立一個除數集,下標為n就表示除數左移n個位置,也就是除數 * 2n-1這個數,要注意除數集的元素也可能在計算過程溢位,要進行判斷,然後逆序將其被被除數減去,如果減去結果小於等於0,則表示這個數也是商的一部分,加入計數。

程式碼展示

class Solution {
public
: int divide(int dividend, int divisor) { int iRet = 0; bool bMinus = false; if(dividend == INT_MIN) { if(divisor == 1) return INT_MIN; if(divisor == -1) return INT_MAX; } if(divisor == INT_MIN) { if(dividend == INT_MIN) return 1; else return 0; } if(dividend == 0) return 0; if(dividend > 0) { bMinus = !bMinus; dividend = -dividend; } if(divisor > 0) { bMinus = !bMinus; divisor = -divisor; } vector<int> divisors = {divisor}; while(dividend - divisors.back() <= divisors.back()) { divisors.push_back(divisors.back() + divisors.back()); } for(int i = divisors.size() - 1; i >= 0; i--) { if(dividend - divisors[i] <= 0) { dividend -= divisors[i]; iRet += 1 << i; } } return bMinus? -iRet: iRet; } };

 

執行結果