剑指Offer 面试题15:二进制中1的个数 Java代码实现

本文介绍两种计算整数二进制表示中1的个数的方法:一是通过逐位检查;二是利用减1相与操作巧妙减少循环次数。通过对比内置方法验证正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指Offer 面试题15:二进制中1的个数

题目:实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如,9的二进制是1001,有两位是1,那么输入9,函数输出2。


看完题目我就想到了Java中Integer类中的bitCount()方法,记得在leetcode上就是这么偷懒完成accepted的,哈哈!正确的解题思路是让1和该数的二进制表示的每一位相与,若不为零则表示该位是1。遍历二进制表示的每一位并统计结果不为0的次数,就是二进制表示中的1的个数了。容易想到,将输入的数字与1相与,然后将数字一直右移,继续相与。书中说,这样会引起死循环,其实这只是条件判断的区别。比如,输入int类型,那在Java中,就是32位存储的,循环判断32次写死了,就没有问题了;另一种是不右移数字,而是将1一直坐移。下面Java代码就是采用将1左移实现的,其实右移数字也可以。


第一种解法:

public static int numberOfOne(int n){
		int count=0;
		int flag=1;
		for(int i=1;i<=32;i++){
			if((n&flag)!=0)
				count++;
			flag=flag<<1;
		}
		return count;
	}

采用右移数字也行,就像上面代码中for循环直接写死32次,而不是采用书中用while判断是否为0!


第二种解法:

该解法基于这样一个事实:把一个整数减1,在和原数相与,会把改整数二进制表示中的最右边的1变成0。

Java代码如下:

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

只要数字不为0,就说明二进制表示中还存在1,就进行减一相与的操作,能进行这样的操作的次数就是1的个数。这种方法循环次数就是1的个数,循环次数比第一种方法少了。


采用Integer类的bitCount()来检验算法对不对,测试代码如下:

public static void main(String[] args) {
		int[] xArr={0,9,15,-1,-15};
		int [] result=new int[xArr.length];
		int [] result2=new int[xArr.length];
		int [] result3=new int[xArr.length];
		for(int i=0;i<xArr.length;i++){
			result[i]=numberOfOne(xArr[i]);
			result2[i]=Integer.bitCount(xArr[i]);
			result3[i]=numberOfOne2(xArr[i]);
		}
		String s1=Arrays.toString(result);
		String s2=Arrays.toString(result2);
		String s3=Arrays.toString(result3);
		System.out.println("方法1结果="+s1+"\n内置API结果="+s2+"\n"+"方法2结果="+s3);
	}

输出结果:

方法1结果=[0, 2, 4, 32, 29]
内置API结果=[0, 2, 4, 32, 29]
方法2结果=[0, 2, 4, 32, 29]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值