每日編程中遇到任何疑問、意見、建議請公眾號留言或直接撩Q474356284(備註每日編程)
今日問題:
給定一個正整數,輸出它的補數。補數是對該數的二進位表示取反。
注意:
給定的整數保證在32位帶符號整數的範圍內。
你可以假定二進位數不包含前導零位。
示例 1:
輸入: 5
輸出: 2
解釋: 5的二進位表示為101(沒有前導零位),其補數為010。所以你需要輸出2。
示例 2:
輸入: 1
輸出: 0
解釋: 1的二進位表示為1(沒有前導零位),其補數為0。所以你需要輸出0。
解決方法:
首先說一下:
這裡的補數「不是「之前你學過的補碼哦。
雖然在計算機科學中補碼的概念是來源於數學中的補數的。
需要注意的一點是本題求正整數的原碼的時候需要忽略前導零位。
什麼意思呢?
舉個慄子:比如5,二進位是101,那麼它的補數就是010,十進位就是2.
但是!但是!但是!計算機不是這樣想的!
按照int來計算的話,int是多少位的?(下面這段話選看)
(在不同編譯器中,可能不一樣,比如在32位和64位編譯器下,int都是4個字節,也就是32位。(你也許又會問32位和64位為什麼都是4個字節,回答是:這是規定啊!需要說明一下的是指針類型存儲的是所指向變量的地址,所以32位機器只需要32bit,而64位機器需要64bit。)
那麼,int佔用4個字節,32位。
5的二進位就是1000,0000,0000,0000,0000,0000,0000,0101.
則它的反碼就是0111, 1111, 1111,1111, 1111, 1111, 1111,1010.
顯然,將其直接取反,再輸出為十進位就不符合題意了。
算法思想(一):
① 尋找一個掩碼(mask)
要找的這個掩碼的特徵應該是這個樣子的。5的二進位是101,只佔3個bit,那麼這個掩碼的最後3個bit要是0,其餘全部是1。如下所示:
5:0000 0101
掩碼:1111 1000
② 分別取反
~5 :1111 1010
~掩碼:0000 0111
③ 相與
~5 & ~掩碼 = 0000 0010
算法思想二:
return pow(2,int(log2(num))+1) - 1 -num;
//圖片代碼中以注釋的方式寫出。
Java算法思想(三):
return ~num & (Integer.highestOneBit(num) - 1);
以上各個符號的作用:
①Integer.highestOneBit(num):取num的二進位數最左邊的最高位,且高位後面全部補零,最後返回int型的結果。
②-1:因為經過上面的步驟,只有最高位為1其餘位都為0這樣再減一就會導致借位直到借到最高位,結果得到 最高位為0其餘位都為1相當於取反了
③&:對兩個二進位數進行按位與運算,例101& 010得000;
101&111得101。
④~ :對一個數的二進位取反
C++代碼:
C代碼:
Java代碼:
明日題目預告:
唯一摩爾斯密碼詞
國際摩爾斯密碼定義一種標準編碼方式,將每個字母對應於一個由一系列點和短線組成的字符串, 比如: "a" 對應 ".-", "b" 對應 "-...", "c" 對應 "-.-.", 等等。
為了方便,所有26個英文字母對應摩爾斯密碼錶如下:
[".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."]
給定一個單詞列表,每個單詞可以寫成每個字母對應摩爾斯密碼的組合。例如,"cab" 可以寫成 "-.-.-....-",(即"-.-." + "-..." + ".-"字符串的結合)。我們將這樣一個連接過程稱作單詞翻譯。
返回我們可以獲得所有詞不同單詞翻譯的數量。
例如:
輸入: words =["gin", "zen", "gig", "msg"]
輸出: 2
解釋:
各單詞翻譯如下:
"gin"-> "--...-."
"zen"-> "--...-."
"gig"-> "--...--."
"msg"-> "--...--."
共有 2 種不同翻譯, "--...-." 和 "--...--.".
注意: