题目:请实现一个函数,输入一个整数,输出该数二进制表示中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,更多参考:汉明重量