LeetCode 476. Number Complement (數字的補數)C++ JAVA實現
Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.
Note:
- The given integer is guaranteed to fit within the range of a 32-bit signed integer.
- You could assume no leading zero bit in the integer’s binary representation.
Example 1:
Input: 5
Output: 2
Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2.
Example 2:
Input: 1 Output: 0 Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0.
給定一個正整數,輸出它的補數。補數是對該數的二進位制表示取反。
注意:
- 給定的整數保證在32位帶符號整數的範圍內。
- 你可以假定二進位制數不包含前導零位。
示例 1:
輸入: 5
輸出: 2
解釋: 5的二進位制表示為101(沒有前導零位),其補數為010。所以你需要輸出2。
示例 2:
輸入: 1
輸出: 0
解釋: 1的二進位制表示為1(沒有前導零位),其補數為0。所以你需要輸出0。
思路一:計算出num的原碼,再取反求補數。
C++實現:
class Solution { public: int findComplement(int num) { vector <int> temp; while(num) { temp.push_back(num%2); num /= 2; } int sum = 0 , j = 0; for(int i = 0; i < temp.size(); i++) { temp[i] = temp[i] > 0? 0 : 1; sum += temp[i]*pow(2,j); j++; } return sum; } };
C++程式碼實現二:
class Solution {
public:
int findComplement(int num)
{
int tmp = num, count = 0;
if(num == 0)
return 1;
while(tmp)
{
tmp = tmp &(tmp -1);
count++;
}
for(int i = 0; i < 32 && count; i++)
{
if(num & (1 << i))
{
count--;
}
else
{
tmp |= (1 << i);
}
}
return tmp;
}
};
思路二:
如果我們能知道該數最高位的1所在的位置,就可以構造一個長度和該資料所佔位置一樣長的一個掩碼mask,然後概述和mask進行異或即可。
例如:5的二進位制是101,我們的構造的掩碼為mask=111,兩者異或則為010,即是所要的結果。
java程式碼實現一:
public class Solution {
public int findComplement(int num) {
int mask = 1, temp = num;
while(temp > 0) {
mask = mask << 1;
temp = temp >> 1;
}
return num^(mask-1);
}
}
java程式碼實現二:
public class Solution {
public int findComplement(int num) {
int mask = (Integer.highestOneBit(num) << 1) - 1;
return num^mask;
}
}
Integer.highestOneBit(i)是一個什麼樣的函式呢?通過檢視文件得知,這個函式的作用是取 i 這個數的二進位制形式最左邊的最高一位且高位後面全部補零,最後返回int型的結果。
來看下 Integer.highestOneBit (i) 這個函式的實現程式碼:
publicstaticinthighestOneBit(int i) { // HD, Figure 3-1 i |= (i >> 1); i |= (i >> 2); i |= (i >> 4); i |= (i >> 8); i |= (i >> 16); return i - (i >>> 1); }
1、第一步的作用是把最高位1右移移位,並與原資料按位取或。那麼這就使得最高位和它的下一位是連續兩個1。
2、第二步的作用是把剛剛移位得到連續兩個1繼續右移兩位並與原資料按位取或。那麼這就使得最高兩位和它的下兩個連續位組成四個連續的1。
3、 以此類推,最終得到的i是從開始的最高位到結束全是1。並減去i不帶符號的右移一位,即可得到一個int資料的最高位的值。
4、上述情況是針對於i不為零和負數的情況,如果i為零,那麼得到的結果始終為零。如果i位負數,那麼得到的結果始終是-2147483648。即等於Integer.MIN_VALUE。(原因在於負數的最高位始終為1,即是負數的符號位)
此函式的最重要理解點在與要始終把握二進位制的最高位進行運算處理,那麼對於函式中的右移一位、兩位、四位、八和十六位就好理解了。同理,對於long型別的取最高位運算應該需要加一條語句 i|=(i>>32); 原因在於long型別在Java中是64位的。 Long型別的hightestOneBit(i)程式碼如下:
public static long highestOneBit(long i) { // HD, Figure 3-1 i |= (i >> 1); i |= (i >> 2); i |= (i >> 4); i |= (i >> 8); i |= (i >> 16); i |= (i >> 32); return i - (i >>> 1); }
java程式碼實現三:
public class Solution {
public int findComplement(int num) {
return ~num & (Integer.highestOneBit(num) - 1);
}
}
java程式碼實現四:
public class Solution {
public int findComplement(int num) {
char[] ch = Integer.toBinaryString(num).toCharArray();
int ret = 0;
for(int i = 0; i < ch.length; i++) {
if(ch[i] == '0') {
ret += Math.pow(2, ch.length - i - 1);
}
}
return ret;
}
}
java程式碼實現五:
class Solution {
public int findComplement(int num) {
String str=Integer.toBinaryString(num);
char[] a=str.toCharArray();
char[] b=new char[a.length];
for(int i=0;i<a.length;i++){
if(a[i]=='0'){
b[i]='1';
}else if(a[i]=='1'){
b[i]='0';
}
}
String c=new String(b);
int nums=Integer.parseInt(c,2);
return nums;
}
}