寫一個函式,求兩個整數之和,要求在函式體內不得使用 “+”、“-”、“*”、“/” 四則運算子號。
示例:
輸入: a = 1, b = 1
輸出: 2
提示:
a, b 均可能是負數或 0
結果不會溢位 32 位整數
方法一:位運算
解題思路
本題考查對位運算的靈活使用,即使用位運算實現加法。
設兩數字的二進位制形式 a,b,其求和 s = a + b,a(i) 代表 a 的二進位制第 i 位,則分為以下四種情況:
a(i) | b(i) | 無進位和 n(i) | 進位 c(i+1) |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
觀察發現,無進位和 與 異或運算 規律相同,進位 與 與運算 規律相同(並需左移一位)。因此,無進位和 n 與進位 c 的計算公式如下:
n = a ⊕ b 非進位和:異或運算
c = a & b << 1 進位:與運算 + 左移一位
(和 s)= (非進位和 n) + (進位 c)
。即可將 s = a + b
轉化為:s = a + b => s = n + c
迴圈求 n 和 c,直至進位 c = 0;此時 s = n,返回 n 即可。
Q : 若數字 aa 和 bb 中有負數,則變成了減法,如何處理?
A : 在計算機系統中,數值一律用 補碼 來表示和儲存。補碼的優勢: 加法、減法可以統一處理(CPU只有加法器)。因此,以上方法 同時適用於正數和負數的加法 。
程式碼
class Solution {
public int add(int a, int b) {
while(b != 0) { // 當進位為 0 時跳出
int c = (a & b) << 1; // c = 進位
a ^= b; // a = 非進位和
b = c; // b = 進位
}
return a;
}
}
複雜度分析
時間複雜度O(1) :最差情況下(例如 a = 0x7fffffff,b = 1 時),需迴圈 32 次,使用 O(1) 時間;每輪中的常數次位操作使用 O(1) 時間。
空間複雜度O(1) :使用常數大小的額外空間。
個人理解
以 9 + 7 為例,詳細手動模擬一下步驟:
十進位制模擬
第一次迴圈,計算 9 + 7:
無進位和:9 + 7 = 6。
進位:個位進一位為 1,進到十位了,所以要 * 10,即 10。
第二次迴圈,計算 6 + 10:
無進位和:
個位:0 + 6 = 6
十位:1 + 0 = 1
結果為 16
進位:個位無進位,十位無進位,
所以最終結果為 16。
二進位制模擬
9 的二進位制為:1001
7 的二進位制位:111
第一次迴圈,計算 1001 + 111:
無進位和(異或):1001 ^ 111 = 1110
進位(與):1001 & 111 = 1
十進位制進位就應該 x10,二進位制進位就得左移一位,所以 1 << 1 = 10
第二次迴圈,計算 1110 + 10:
無進位和(異或):1110 ^ 10 = 1100
進位(與):1110 & 10 << 1 = 10 < < 1 = 100
第三次迴圈,計算 1100 + 100:
無進位和(異或):1100 ^ 100 = 1000
進位(與):1100 & 100 << 1 = 100 < < 1 = 1000
第四次迴圈,計算 1000 + 1000:
無進位和(異或):1000 ^ 1000 = 0000
進位(與):1000 & 1000 << 1 = 1000 < < 1 = 10000
第五次迴圈,計算 0000 + 10000:
無進位和(異或):0000 ^ 10000 = 10000
進位(與):0000 & 10000 << 1 = 00000 < < 1 = 000000
這個時候就該結束了,因為此時無進位了。
此時 10000 的值就是最終結果,換成十進位制為 16。
為什麼十進位制相加迴圈次數這麼少?而二進位制迴圈次數這麼多呢? 因為二進位制位數多,碰到特別情況,比如該情況,一位一位向上進,所以迴圈次數就多了。
那麼什麼時候結束迴圈呢? 就是沒有進位的時候,不需要再加了。
為什麼要有迴圈呢? 因為相加就會產生進位,進位了說明沒算完,需要繼續加上進位,知道沒有進位。
題解來源
作者:jyd
連結:leetcode-cn.com/problems/bu-yong-j...
來源:力扣(LeetCode)
方法二:奇思妙想解法
程式碼
真沒有運算子!!
class Solution:
def add(self, a: int, b: int) -> int:
result = [a,b]
return sum(result)
題解來源
作者:luyao777
連結:leetcode-cn.com/problems/bu-yong-j...
來源:力扣(LeetCode)
來源:力扣(LeetCode)
連結:leetcode-cn.com/problems/bu-yong-j...
本作品採用《CC 協議》,轉載必須註明作者和本文連結