更多精彩內容,請關注【力扣中等題】。
題目
難度:★★☆☆☆
類型:數學
給定兩個整數,被除數 dividend 和除數 divisor。將兩數相除,要求不使用乘法、除法和 mod 運算符。
返回被除數 dividend 除以除數 divisor 得到的商。
說明
被除數和除數均為 32 位有符號整數。
除數不為 0。
假設我們的環境只能存儲 32 位有符號整數,其數值范圍是 [?231, 231 ? 1]。本題中,如果除法結果溢出,則返回 231 ? 1。
示例
示例 1
輸入: dividend = 10, divisor = 3
輸出: 3
示例 2
輸入: dividend = 7, divisor = -3
輸出: -2
解答
方案1:二分法
由于商不會大于被除數,因此可以把題目當做一個查找問題,就可以使用二分法解決。在程序開始,首先要對結果到的正負號進行判斷,并將被除數和輸出取絕對值。類似題目【題目69. x的平方根】
構建一個連續遞增數組,數組最小值為零,最大值為被除數divident,并取出該數組最中間的元素mid(如果數組有偶數個元素,我們取中點偏左的數字);
查看mid*divisor,(mid+1)*divisor與被除數的關系,分一下三種情況:
(1)dividend < mid*divisor,表明中點處的元素過大,拋棄數組右半部分;
(2)mid*divisor <= dividend < (mid+1)*divisor,表明中點處的元素即為所求,直接返回;
(3)(mid+1)*divisor <= dividend,表明中點處的元素過小,拋棄數組右半部分;每次迭代,都要更新數組并取新的中點。
class Solution:
def divide(self, dividend: int, divisor: int) -> int:
# 確定結果的正負
flag = 1 if divisor > 0 and dividend > 0 or divisor < 0 and dividend < 0 else -1
# 操作數取絕對值
dividend, divisor = abs(dividend), abs(divisor)
# 初始化上下邊界
low, upper = 0, dividend
# 執行循環
while low <= upper:
# 二分查找中點
middle = (low + upper) // 2
# 情況1,中點*除數>被除數,說明中點處值偏大,拋棄右半部分
if dividend < middle * divisor:
upper = middle - 1
# 情況2,(中點+1)*除數<被除數,說明中點處的值偏小,拋棄左半部分
elif (middle + 1) * divisor <= dividend:
low = middle + 1
# 情況3,中點+1 * 除數 < 被除數 < (中點+1) * 除數,獲得商,并限制取值范圍
elif middle * divisor <= dividend < (middle + 1) * divisor:
return min(max(-2 ** 31, flag * middle), 2 ** 31 - 1)
如有疑問或建議,歡迎評論區留言~