[LeetCode解題攻略] 29. Divide Two Integers

更新於 發佈於 閱讀時間約 9 分鐘

題目描述

實作一個函數 divide(dividend, divisor),計算兩個整數 dividenddivisor 的商,並返回其結果。

注意:不允許使用乘法、除法和取模運算子。

條件限制

  1. 如果結果超出 32 位整數範圍 [-2^31, 2^31 - 1],則返回 2^31 - 1 或 -2^31。
  2. 被除數 dividend和除數 divisor的範圍是 [-2^31, 2^31 - 1],且除數不為 0。

範例 1:

輸入

dividend = 10, divisor = 3

輸出

3

解釋:10 除以 3,商為 3。

範例 2:

輸入

dividend = 7, divisor = -3

輸出

-2

解釋:7 除以 -3,商為 -2。

範例 3:

輸入

dividend = -2147483648, divisor = -1

輸出

2147483647

解釋:結果超出 32 位整數範圍,返回 2^31 - 1。


解題思路

要解決這道題,我們需要考慮以下幾個方面:

  1. 符號處理
    • 商的符號由被除數和除數的符號決定,兩者異號則商為負數。
  2. 模擬除法
    • 使用減法或位運算來模擬除法運算。
  3. 邊界條件
    • 如果結果超出 32 位整數範圍,需返回邊界值。
    • 特殊情況如 dividend = -2^31, divisor = -1。

解法一:減法模擬

思路

我們可以用多次減法來模擬除法運算:

  1. 不斷從被除數中減去除數,計算可以減去的次數。
  2. 注意符號的處理。

詳細步驟

  1. 紀錄結果的符號(正負)。
  2. 取絕對值處理,簡化計算。
  3. 使用一個迴圈不斷從被除數中減去除數,直到被除數小於除數。
  4. 檢查結果是否超出 32 位整數範圍。

程式碼實現

class Solution:
def divide(self, dividend: int, divisor: int) -> int:
if dividend == -2**31 and divisor == -1:
return 2**31 - 1 # 處理溢出情況

# 確定結果的正負
negative = (dividend < 0) ^ (divisor < 0)

# 取絕對值進行計算
dividend, divisor = abs(dividend), abs(divisor)

result = 0
while dividend >= divisor:
dividend -= divisor
result += 1

# 恢復符號
result = -result if negative else result

return max(-2**31, min(result, 2**31 - 1))

時間與空間複雜度

  • 時間複雜度:O(n),其中 n=商值,因為每次減去一個除數。
  • 空間複雜度:O(1)。

解法二:倍增減法

思路

用單次減法效率較低,尤其是被除數很大時。我們可以採用指數倍增的方式來加速:

  1. 每次減去當前除數的倍數(例如 2⋅除數,4⋅除數 等),倍數每次翻倍。
  2. 當倍增的除數超過被除數時,回退到上一個倍數。

詳細步驟

  1. 紀錄符號並取絕對值。
  2. 使用一個倍增方式快速逼近被除數。
  3. 當倍數無法繼續增加時,將被除數減去當前倍增的值,並繼續迴圈。

程式碼實現

class Solution:
def divide(self, dividend: int, divisor: int) -> int:
if dividend == -2**31 and divisor == -1:
return 2**31 - 1 # 處理溢出情況

# 確定結果的正負
negative = (dividend < 0) ^ (divisor < 0)

# 取絕對值進行計算
dividend, divisor = abs(dividend), abs(divisor)

result = 0
while dividend >= divisor:
temp_divisor, multiple = divisor, 1
while dividend >= (temp_divisor << 1):
temp_divisor <<= 1
multiple <<= 1

dividend -= temp_divisor
result += multiple

# 恢復符號
result = -result if negative else result

return max(-2**31, min(result, 2**31 - 1))

時間與空間複雜度

  • 時間複雜度:O(logn),其中 n=被除數。倍增法每次將剩餘的被除數減小到一半。
  • 空間複雜度:O(1)。

解法三:位運算(位移法)

思路

位運算的基本思路是利用位移操作來高效計算倍增。通過計算 divisor 向左移動幾位可以逼近 dividend,從而快速確定商的大小。

詳細步驟

  1. 紀錄結果符號並取絕對值。
  2. 將除數不斷向左移位,直到超過被除數。
  3. 每次找到一個可以減去的倍數,更新被除數並累加到結果。

程式碼實現

class Solution:
def divide(self, dividend: int, divisor: int) -> int:
if dividend == -2**31 and divisor == -1:
return 2**31 - 1 # 處理溢出情況

# 確定結果的正負
negative = (dividend < 0) ^ (divisor < 0)

# 取絕對值
dividend, divisor = abs(dividend), abs(divisor)

result = 0
for i in range(31, -1, -1):
if (dividend >> i) >= divisor:
result += 1 << i
dividend -= divisor << i

# 恢復符號
result = -result if negative else result

return max(-2**31, min(result, 2**31 - 1))

時間與空間複雜度

  • 時間複雜度:O(log⁡n),其中 n=被除數。最多進行 32 次迴圈操作。
  • 空間複雜度:O(1)。

總結

  • 暴力減法:簡單直觀,但效率較低。
  • 倍增減法:用指數倍增來優化,效率更高。
  • 位運算:利用位移操作,進一步優化時間複雜度。

倍增法與位移法是實際開發中常用的高效解法。如果你有任何疑問,歡迎留言討論!

留言
avatar-img
留言分享你的想法!
avatar-img
追極光的北極熊|軟體工程師的小天地
11會員
163內容數
歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
2025/04/04
給定一個非負整數陣列 nums,其中 nums[i] 代表你在索引 i 處最多可以向右跳幾步。 請判斷是否能夠從索引 0 跳到最後一個索引。
2025/04/04
給定一個非負整數陣列 nums,其中 nums[i] 代表你在索引 i 處最多可以向右跳幾步。 請判斷是否能夠從索引 0 跳到最後一個索引。
2025/03/28
給定一個 m x n 的矩陣 matrix,請按照 螺旋順序(spiral order) 返回矩陣中的所有元素。
2025/03/28
給定一個 m x n 的矩陣 matrix,請按照 螺旋順序(spiral order) 返回矩陣中的所有元素。
2025/03/20
這道題是 LeetCode 的經典題之一,要求我們找出 一個子陣列,使其和最大,並返回這個最大和的數值。
2025/03/20
這道題是 LeetCode 的經典題之一,要求我們找出 一個子陣列,使其和最大,並返回這個最大和的數值。
看更多
你可能也想看
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
題目敘述 Check If Array Pairs Are Divisible by k 給定一個長度為偶數的整數陣列arr,和一個整數k 。 我們想把陣列元素兩兩一組組成pair,使得每個pair的總和可以被k整除。 如果做得到,返回True。 如果不行,返回False。
Thumbnail
題目敘述 Check If Array Pairs Are Divisible by k 給定一個長度為偶數的整數陣列arr,和一個整數k 。 我們想把陣列元素兩兩一組組成pair,使得每個pair的總和可以被k整除。 如果做得到,返回True。 如果不行,返回False。
Thumbnail
給定一個整數陣列arr,和一串區間XOR請求queries。 請計算queries所請求的區間XOR值,並且以陣列的形式返回答案。
Thumbnail
給定一個整數陣列arr,和一串區間XOR請求queries。 請計算queries所請求的區間XOR值,並且以陣列的形式返回答案。
Thumbnail
題目敘述 題目會給我們一個陣列,要求我們返回 兩數之和=target所在的陣列索引值。 題目還額外保證,一定剛好有一組解。 測試範例 Example 1: Input: nums = [2,7,11,15], target = 9 Output: [0,1]
Thumbnail
題目敘述 題目會給我們一個陣列,要求我們返回 兩數之和=target所在的陣列索引值。 題目還額外保證,一定剛好有一組解。 測試範例 Example 1: Input: nums = [2,7,11,15], target = 9 Output: [0,1]
Thumbnail
題目:建立一個函數,該函數返回給定最小 4 個正整數的數組的兩個最低正數的總和。不會傳入浮點數或非正整數。例如,當一個數組像 [19, 5, 42, 2, 77], 輸出應該是 7。 [10, 343445353, 3453445, 3453545353453] 應該回來 3453
Thumbnail
題目:建立一個函數,該函數返回給定最小 4 個正整數的數組的兩個最低正數的總和。不會傳入浮點數或非正整數。例如,當一個數組像 [19, 5, 42, 2, 77], 輸出應該是 7。 [10, 343445353, 3453445, 3453545353453] 應該回來 3453
Thumbnail
題目如下: Input: numbers = [2,7,11,15], target = 9 Output: [1,2]
Thumbnail
題目如下: Input: numbers = [2,7,11,15], target = 9 Output: [1,2]
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News