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


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

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

題目

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

思路

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

  方法一:”與運算“有一個性質:通過與對應位上為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,就只需要循環判斷幾次。

測試用例

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

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

  3.0

完整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位數字,其正數的邊界值為1、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實現合集  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM