「leetcode」29.兩數相除

原題

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

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

示例 1:bash

輸入: dividend = 10, divisor = 3
輸出: 3
複製代碼

示例 2:ide

輸入: dividend = 7, divisor = -3
輸出: -2
複製代碼

說明:ui

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

思路

解題思路來自評論區的foxleezh大神。題目中明確不能使用/, 咱們能夠右移模擬除法,右移能夠等價於下面的等式spa

  • 右移1位,等價於,除以2的1次方。
  • 右移2位,等價於,除以2的2次方。
  • 右移3位,等價於,除以2的3次方。
a / 2 === a >> 1
a / 4 === a >> 2
a / 8 === a >> 3
複製代碼

被除數 / 除數 === 商……餘數 等價於 ➡️ 被除數 === (商 * 除數) + 餘數 等價於 ➡️ (被除數 - 餘數) / 商 === 除數code

假設,咱們的被除數等於100,除數等於5。get

根據等式(被除數 - 餘數) / 商 == 除數,咱們首先要找到,100除以多少最接近於除數(或者說,除以多少時會大於等於除數)。it

當100除以2^31時,結果相較於除數會很是的小。咱們使用循環逐漸減小右移的位數,逐漸逼近除數,當100 >>> 4(100 / 16)時等於6,大於等於5。io

這時,咱們能夠確定**商是大於16(2的四次方)**的某個數(或者說,100至少包含16個5)。

咱們使用被除數 = 被除數 - 16 * 除數等於還剩下的沒有除乾淨的數。目前還剩下20。咱們再次使用上述的方法,再次逼近除數(獲取20裏還有幾個5)。最終獲得最後的結果。

代碼

/** * @param {number} dividend * @param {number} divisor * @return {number} */
var divide = function(dividend, divisor) {
    
    // 判斷結果是否爲負數
    const isNegative = (dividend ^ divisor) < 0
    
    // 統一按正數處理
    dividend = Math.abs(dividend)
    divisor = Math.abs(divisor)
    
    if (dividend === 0) {
        return 0
    }
    
    if (dividend === 2147483648 && divisor === 1) {
        // 避免結果溢出
        return isNegative ? -dividend/divisor : dividend/divisor - 1
    }
    
    let result = 0
    
    for (let i = 31; i >= 0; i--) {
        // 注意這裏須要使用無符號右移
        if ((dividend >>> i) >= divisor) {
            result += Math.pow(2, i)
            dividend -= Math.pow(2, i) * divisor
        }
    }
    
    return isNegative ? -result : result
};
複製代碼
相關文章
相關標籤/搜索