剑指offer-----二进制中1的个数

/**
 * 剑指offer面试题10:二进制中1的个数
 * 
 * 题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,
 * 有2位是1。因此如果输入9,该函数输出2.
 * 
 * 思路1:首先把n和1做与运算,判断n的最低位是不是1.接着把1左移一位得到2,再和n做与运算,就能判断n的次位是不是1....
 * 这样反复左移,每次就能判断n的其中一位是不是1.
 *
 * 思路2:把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制表示种有多少个1,就可以
 * 进行多少次这样的操作。
 * 
 * 左移运算: 00001010 << 2 = 00101000      10001010 << 3 = 01010000  
 * 右移运算: 00001010 >> 2 = 00000010      10001010 >> 3 = 11110001  
 * 注意:当右移时,如果数字是一个无符号数值,则最左边的n位用0填补。如果数字是一个有符号数值,则用数字的符号位替补最左边的n位。
 * 
 * 考查:二进制及位运算的理解
 * 
 * 相关题目:
 * 1.用一条语句判断一个整数是不是2的整数次方。一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他位是0.
 *    解法: 若(n-1)&n == 0,则该整数是2的整数次方;否则不是。
 * 
 * 2.输入两个整数m和n,计算需要改变m的二进制表示种的多少位才能得到n。比如10的二进制表示为1010,13的二进制表示为1101,需要
 * 改变1010中的3位才能得到1101.
 *    解法: 先求这两个数的异或,然后再统计异或结果中1的位数。   
 */
public class BitOperation {
		
	//常规解:用左移代替右移,因为右移在负数的时候,会陷入死循环
	public static int numberOfOne(int n) {
		int count = 0;
		int flag = 1;
		//这里不会无限循环下去,一个int类型是32位,所以这里循环32次就会停止。
		while(flag != 0) {
			if((n&flag)!= 0) {
				count++;
			}
			flag = flag << 1;
//			System.out.println("flag:"+flag);
		}
		return count;
	}
	
	//最优解:每次减1,再和原数进行与运算
	public static int numberOfOne_1(int n) {
		int count = 0;
		while(n != 0) {
			count++;
			n = (n-1)&n;
		}
		return count;
	}
	
	//相关题目2
	public static int changeNumber(int m,int n) {
		int count = 0;
		//先异或
		int temp = m ^ n;
		//在统计1的个数
		while(temp != 0) {
			count++;
			temp = (temp-1)&temp;
		}
		return count;
	}

	public static void main(String[] args) {
		System.out.println(numberOfOne(9));
		System.out.println();
		System.out.println(numberOfOne_1(9));
		System.out.println();
		System.out.println(changeNumber(10,13));
	}
}

 

你可能感兴趣的:(剑指Offer)