求二进制数中1的个数(剑指offer10 编程之美2.1)

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

1.借助栈,先求这个数的二进制表示,然后计算1的个数

int oneCountWithStack(unsigned int n) {
	int count = 0;
	int top = -1;
	int* x = new int[32];
	while (n) {
		x[++top] = n % 2;
		n = n / 2;
	}

	for (int i = top; i >= 0; --i) {
		if (x[i] == 1) {
			count = count + x[i];
		}
	}

	delete x;

	return count;
}

2.不再借助栈,将一个数转换为二进制数的过程中计算1的个数

int oneCountWithoutStack(unsigned int n) {
	int count = 0;
	while (n) {
		if (n % 2 == 1) {
			count++;
		}

		n = n / 2;
	}

	return count;
}

3.不再需要判断二进制中某位是否是1

int oneCountWithoutIf(unsigned int n) {
	int count = 0;

	while (n) {
		count = count + n % 2;
		n = n / 2;
	}

	return count;
}

4.用位运算替代除法和取模运算

int oneCountWithBit(unsigned int n) {
	int count = 0;

	while (n) {
		count = count + (n & 1);
		n = n >> 1; //右移可能引起死循环(n为负数时)
	}

	return count;
}

5.前面4中求解方法只适用于n为非负数的情况,下面这种两种解法对于负数也可以使用

int oneCountWithSigned(int n) {
	int count = 0;
	unsigned int flag = 1;
	while (flag) {
		if (n & flag) {
			++count;
		}

		flag = flag << 1;
	}

	return count;
}

6.效率更高的解法--基于这样一种事实即 X 与 X-1 相得到的最低位永远是 0







 减 1 操作将最右边的符号从 0 变到 1,从 1 变到 0,操作将会移除最右端的 1。如果最初 X 有 N 个 1,那么经过 N 次这样的迭代运算,X 将减到 0。

int oneCount(int n) {
	int count = 0;

	while (n) {
		n = n & (n - 1);
		++count;
	}

	return count;
}

测试代码

#include<iostream>
using namespace std;

int main() {
	//测试用例{-2147483647,-4,-3,-1,0,1,2,3,4,2147483647,4294967296}

	int n = 0;
	cout << "输入一个整数:" << endl;
	while (cin >> n) {
		cout << "unsigned(n)=" << unsigned(n) << endl;
		cout << n << "的二进制表示中1的个数是:" << oneCountWithStack(n) << endl;
		cout << n << "的二进制表示中1的个数是:" << oneCountWithoutStack(n) << endl;
		cout << n << "的二进制表示中1的个数是:" << oneCountWithoutIf(n) << endl;
		cout << n << "的二进制表示中1的个数是:" << oneCountWithBit(n) << endl;
		cout << n << "的二进制表示中1的个数是:" << oneCountWithSigned(n) << endl;
		cout << n << "的二进制表示中1的个数是:" << oneCount(n) << endl;
	}

	return 0;
}


注:部分算法参照自编程之美与剑指offer,更多参考:汉明重量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值