stm32 整數加法迴圈時間_劍指 Offer 65. 不用加減乘除做加法 leetcode 劍指offer系列...
阿新 • • 發佈:2020-12-21
技術標籤:stm32 整數加法迴圈時間
點選專輯上方“藍字”關注我吧題目難度: 簡單
原題連結[1]
今天繼續更新劍指 offer 系列, 老樣子晚上 6 點 45 分準時更新公眾號 每日精選演算法題, 大家記得關注哦~ 另外在公眾號裡回覆 offer 就能看到劍指 offer 系列當前連載的所有文章了
題目描述
寫一個函式,求兩個整數之和,要求在函式體內不得使用 “+”、“-”、“*”、“/” 四則運算子號。
- a, b 均可能是負數或 0
- 結果不會溢位 32 位整數
題目樣例
示例
- 輸入: a = 1, b = 1
- 輸出: 2
題目思考
- 不能用四則運算, 那還能用哪些運算子來實現呢?
解決方案
思路
- 相比昨天的題目劍指 Offer 64. 求 1+2+…+n - leetcode 劍指 offer 系列, 這道題目限制少了很多, 至少迴圈/條件判斷/位運算這些都能用了
- 我們先來嘗試分析數字的二進位制表示, 看看能否用位運算來替代加法
- 如果某一位的兩個數字都是 1, 那麼這一位的加法就會產生進位, 所以
與
可以用來計算進位, 而且顯然進位是要左移一位的 - 接下來考慮如何得到當前位的加法結果.
異或
在兩個數字都為 1 或者都為 0 的情況下結果是 0, 否則結果是 1, 換言之異或就是不帶進位的加法 - 將上面兩步結合在一起, 我們就能把
a+b
轉換成((a&b)<<1)+(a^b)
- 注意最終進位一定能變成 0, 這是因為如果有進位的話, 進位是會不斷左移的, 而題目保證最終結果不會溢位, 那麼經過若干次迴圈後, 一定會達到一個不需要進位的狀態, 不然無限左移就會溢位了
- C++/JAVA 等語言分析到這裡就 OK 了, 但 python 需要特別處理負數問題. 因為 python 的負數表示方法不是像其他語言那樣的 32 位補碼, 而是更高位也全是 1, 這樣在處理負數的時候必須手動模擬 32 位補碼, 才能正確得出結果, 不然最後結果就不滿足 python 正確的負數表示方式, 而變成無符號正數了
- 所以我們需要先將負數轉成 32 位補碼 (
&0xFFFFFFFF
, 正數仍為自身, 負數相當於 32 位補碼形式, 因為去掉了更高位上的 1), 然後利用上述結果求完之後, 如果結果是負數(>0x7FFFFFFF
)的話再轉成正常的 python 負數表示方式(~(a ^ 0xFFFFFFFF)
, 即先對低 32 位的取反, 更高位不變, 然後整體再取反, 從而將大於等於 32 位的數字重新轉成 1) - 下面程式碼額外列出了 Java 版本, 方便大家對比. Java 的負數就是 32 位補碼錶示, 所以不需要額外進行處理
複雜度
- 時間複雜度 O(logN): 最多需要遍歷所有位數, 數字 N 的位數為 logN
- 空間複雜度 O(1): 只需要維護常數個變數
程式碼
python 3
classSolution:
defadd(self,a:int,b:int)->int:
#32位數掩碼
mask=0XFFFFFFFF
#32位數的最大正數
posMx=0X7FFFFFFF
whileb!=0:
#a是不帶進位的和,都要轉成32位整數
# b是進位, 都要轉成32位整數
#迴圈直到進位為0,那麼a就是最終結果
smwithoutcarry=(a^b)&mask
carry=((a&b)<1)&mask
a,b=smwithoutcarry,carry
#最終如果是32位負數的話,需要將其轉回python正常的負數表示形式(高於32位的全是1,而不是32位負數那樣更高位全為0),做法是先對低32位的取反,更高位不變,然後整體再取反,從而將大於等於32位的數字重新轉成1
returnaifa<=posMxelse~(a^mask)
Java
classSolution{
publicintadd(inta,intb){
while(b!=0)
{
intsmwithoutcarry=a^b;
intcarry=(a&b)<1;
a=smwithoutcarry;
b=carry;
}
returna;
}
}
參考資料
[1]原題連結: https://leetcode-cn.com/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof/
你的每個贊和在看,我都喜歡!