【Java】 劍指offer(14) 二進制中1的個數

本文參考自《劍指offer》一書,代碼採用Java語言。html

更多:《劍指Offer》Java實現合集  java

題目

  請實現一個函數,輸入一個整數,輸出該數二進制表示中1的個數。例如把9表示成二進制是1001,有2位是1。所以若是輸入9,該函數輸出2。面試

思路

  遇到與二進制有關的題目,應該想到位運算(與、或、異或、左移、右移)。ide

  方法一:」與運算「有一個性質:經過與對應位上爲1,其他位爲0的數進行與運算,能夠某一整數指定位上的值。這道題中,先把整數n與1作與運算,判斷最低位是否爲1;接着把1左移一位,與n作與運算,能夠判斷次低位是否爲1……反覆左移,便可對每個位置都進行判斷,從而能夠得到1的個數。這種方法須要循環判斷32次。函數

  方法二(better):若是一個整數不爲0,把這個整數減1,那麼原來處在整數最右邊的1就會變爲0,原來在1後面的全部的0都會變成1。其他全部位將不會受到影響。再把原來的整數和減去1以後的結果作與運算,從原來整數最右邊一個1那一位開始全部位都會變成0。所以,把一個整數減1,再和原來的整數作與運算,會把該整數最右邊的1變成0。這種方法,整數中有幾個1,就只須要循環判斷幾回。post

測試用例測試

  1.正數(包括邊界值一、0x7FFFFFFF)url

  2.負數(包括邊界值0x80000000、0xFFFFFFFF)spa

  3.0code

完整Java代碼

(含測試代碼)

/**
 * 
 * @Description 面試題15:二進制中1的個數
 *
 * @author yongh
 * @date 2018年9月17日 下午3:01:16
 */

// 題目:請實現一個函數,輸入一個整數,輸出該數二進制表示中1的個數。例如
// 把9表示成二進制是1001,有2位是1。所以若是輸入9,該函數輸出2。

public class NumberOf1InBinary {
	public int NumberOf1_Solution1(int n) {
		int count = 0;
		int flag = 1;
		while (flag != 0) {
			if ((flag & n) != 0)
				count++;
			flag = flag << 1;
		}
		return count;
	}

	public int NumberOf1_Solution2(int n) {
		int count = 0;
		while (n != 0) {
			count++;
			n = (n - 1) & n;
		}
		return count;
	}

	// =========測試代碼=========

	void test(String testName, int n, int expected) {
		if (testName != null)
			System.out.println(testName + ":");
		if (NumberOf1_Solution1(n) == expected) {
			System.out.print("    soluton1:" + "passed  ");
		} else {
			System.out.print("    solution1:" + "failed  ");
		}

		if (NumberOf1_Solution2(n) == expected) {
			System.out.println("soluton2:" + "passed  ");
		} else {
			System.out.println("solution2:" + "failed  ");
		}
	}
	
	void test1() {
		test("Test for 0", 0, 0);
	}
	
	void test2() {
		test("Test for 1", 1, 1);
	}
	
	void test3() {
		test("Test for 10", 10, 2);
	}
	
	void test4() {
		test("Test for 0x7FFFFFFF", 0x7FFFFFFF, 31);
	}
	
	void test5() {
		test("Test for 0xFFFFFFFF", 0xFFFFFFFF, 32);
	}
	
	void test6() {
		test("Test for 0x80000000", 0x80000000, 1);
	}
	
	public static void main(String[] args) {
		NumberOf1InBinary demo = new NumberOf1InBinary();
		demo.test1();
		demo.test2();
		demo.test3();
		demo.test4();
		demo.test5();
		demo.test6();
	}
}

    

Test for 0:
    soluton1:passed  soluton2:passed  
Test for 1:
    soluton1:passed  soluton2:passed  
Test for 10:
    soluton1:passed  soluton2:passed  
Test for 0x7FFFFFFF:
    soluton1:passed  soluton2:passed  
Test for 0xFFFFFFFF:
    soluton1:passed  soluton2:passed  
Test for 0x80000000:
    soluton1:passed  soluton2:passed  
NumberOf1InBinary

 

收穫

  1.與二進制有關的題目要往位運算方面想,複習一下:二進制位運算的幾個用法

  2.注意:負數右移仍是負數!即若是對n=0x8000 0000右移,最高位的1是不會變的。若是這道題目經過令n=n>>1來計算n中1的個數,該數最終會變成0xFFFF FFFF而陷入死循環!

  3.把一個整數減1,再和原來的整數作與運算,會把該整數最右邊的1變成0。這種方法必定要緊緊記住,不少狀況下均可能用到,例如:

   1)一句話判斷一個整數是否爲2的整數次方;

   2)對兩個整數m和n,計算須要改變m二進制表示中的幾位才能獲得n。

  4.與數字操做有關的題目,測試時注意邊界值的問題。對於32位數字,其正數的邊界值爲一、0x7FFFFFFF,負數的邊界值爲0x80000000、0xFFFFFFFF。

  5.幾個細節問題

   1)flag=flag<<1,而不是隻寫一句flag<<1;

   2)flag&n!=0,而非flag&n==1; 也就不能寫成count+=(flag&1)了

   3)if語句中,不能寫爲if(flag&n!=0) ,而要寫成 if((flag&n)!=0),須要注意一下

 

更多:《劍指Offer》Java實現合集 

相關文章
相關標籤/搜索