題目要求:
編寫一個函數,輸入是一個無符號整數,返回其二進制表達式中數字位數爲 ‘1’ 的個數(也被稱爲漢明重量)。
示例 1:
輸入:00000000000000000000000000001011
輸出:3
解釋:輸入的二進制串 00000000000000000000000000001011 中,共有三位爲 '1'。
1.剛開始想到的最簡單的辦法肯定就是,先將輸入的int n轉換爲二進制形式字符串,然後挨個計算其中的‘1’的個數
//調用Integer函數
public static int hammingWeight(int n) {
String s = Integer.toUnsignedString(n, 2);
// System.out.println(s);
int len = s.length(), count = 0;
for(int i = 0; i < len; i++){
if(s.charAt(i) == '1')
count++;
}
return count;
}
這是一種辦法,但是耗時稍微長一點。
轉化爲二進制的時候使用了Integer庫的函數,toUnsignedString(int n, radix 2)
- public static String toUnsignedString(int i, int radix)
- 以第二個參數指定的基數中的無符號整數值返回第一個參數的字符串表示形式。
- 如果基數小於
Character.MIN_RADIX
或大於Character.MAX_RADIX
,則使用基數10
。 -
請注意,由於第一個參數被視爲無符號值,因此不會打印前導符號。
2.又想了如果不使用自帶函數呢,利用二進制的定義去進行轉換
//利用除法和取餘計算二進制
public static int hammingWeightDivide(int n) {
StringBuilder sb = new StringBuilder();
while (n > 0){
sb.insert(0, String.valueOf(n % 2));
n = n / 2;
}
int len = sb.length(), count = 0;
for(int i = 0; i < len; i++){
if(sb.charAt(i) == '1')
count++;
}
return count;
}
3.最後一種就是位運算:
//位運算, 每一位都與1做“&”運算,都爲1,結果才爲1,可以進行判斷
//需要注意的一個點就是位運算的優先級比較低,需要加上括號
// 第一步 111111010101001010 n
// 000000000000000001 mask
// 第二步 111111010101001010 n
// 000000000000000010 mask
public static int hammingWeightWei(int n) {
int count = 0;
int mask = 1;
for(int i = 0; i < 32; i++){
if((n & mask) != 0)
count++;
//將掩碼左移一位,與下一位作比較
mask <<= 1;
}
return count;
}
位運算中的’&‘運算,計算方法是
如果相對應位都是1,則結果爲1,否則爲0 |
這裏剛好用來做計算’1‘的個數,每一次都int n的一位與1做與運算,如果結果不爲0,那麼就代表該位上的數字是’1‘;count++
之後再將mask中1的位置往左移,利用按位左移運算符可以達到這個效果,接着繼續計算n的後位。
4.接着衍生出了一個新的想法,如果需要將一個無符號位的數轉換成指定位數的二進制形式(不足的位取0)
例: 4的二進制形式是 0100,那麼如果函數指定需要6位數的二進制形式,那麼返回結果就是 000100
/**
* 將一個int數字轉換爲二進制的字符串形式。
* @param num 需要轉換的int類型數據
* @param index要轉換的二進制位數,位數不足則在前面補0
* @return 二進制的字符串形式
*/
public static String toBinary(int num, int index) {
int value = 1 << index| num;
System.out.println(value);
String bs = Integer.toBinaryString(value); // 將value轉換爲二進制形式的字符串
//將最前面的1去掉
return bs.substring(1);
}
這裏解釋一下, 1 利用按位左移運算符, 1 << index, 假設 digits等於6, 那麼原來1的二進制形式是 0000001,按位左移之後就變成了1000000,這個時候再將按位左移之後的結果與num做’或‘運算, “|"運算符的計算方法是,
如果相對應位都是 0,則結果爲 0,否則爲 1 |
那麼1000000
0000100 結果爲 1000100
最後捨去字符串前面的第一位,結果就是 000100,讓結果確定爲6位數。
有符號位和無符號位
無符號數中,所有的位都用於直接表示該值的大小
有符號數中,第一位用來表示正負,後面的位才用來表示大小
比如一個無符號數 1111 0001 代表數值 241 而有符號數 1111 0001 -113
即有符號數第一位, 1代表“-”, 0 代表“+”;
但是java的基本數據類型都是有符號數,
byte、short、char、double、int、long、float都是有符號數