《剑指Offer》面试题10:二进制中1的个数
1 面试题10:二进制中1的个数
知识点
二进制及位运算
题目描述
请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。因此,如果输入9,该函数输出2。
解题思路
(1)可能引起死循环的解法
(2)常规解法
(3)能给面试官带来惊喜的解法
测试用例
代码(原书)
/* 《剑指Offer——名企面试官精讲典型编程题》代码
著作权所有者:何海涛*/
#include "stdio.h"
#include "cstdlib"
//常规解法
int NumberOf1_Solution1(int n)
{
int count = 0;
unsigned int flag = 1;
while (flag)
{
if (n & flag)
count++;
flag = flag << 1;
}
return count;
}
//能给面试官带来惊喜的解法
int NumberOf1_Solution2(int n)
{
int count = 0;
while (n)
{
++count;
n = (n - 1) & n;
}
return count;
}
void Test(int number, unsigned int expected)
{
int actual = NumberOf1_Solution1(number);
if (actual == expected)
printf("Solution1: Test for %p passed.\n", number);
else
printf("Solution1: Test for %p failed.\n", number);
actual = NumberOf1_Solution2(number);
if (actual == expected)
printf("Solution2: Test for %p passed.\n", number);
else
printf("Solution2: Test for %p failed.\n", number);
printf("\n");
}
int main()
{
// 输入0,期待的输出是0
Test(0, 0);
// 输入1,期待的输出是1
Test(1, 1);
// 输入10,期待的输出是2
Test(10, 2);
// 输入0x7FFFFFFF,期待的输出是31
Test(0x7FFFFFFF, 31);
// 输入0xFFFFFFFF(负数),期待的输出是32
Test(0xFFFFFFFF, 32);
// 输入0x80000000(负数),期待的输出是1
Test(0x80000000, 1);
system("pause");
return 0;
}
代码(牛客网)
class Solution {
public:
// 法1:
/*int NumberOf1(int n) {
int count = 0;
while(n)
{
++ count;
n = (n - 1) & n;
}
return count;
}*/
//法2:
int NumberOf1(int n) {
int count = 0;
int num = 1;
while(num)
{
if(n & num)
{
++ count;
}
num = num << 1;
}
return count;
}
};
2 举一反三
把一个整数减去1后再和原来的整数做位与运算,得到的结果相当于是把整数的二进制表示中的最右边一个1变成0.很多二进制问题都可以用这个思路解决。
相关题目1:用一条语句判断一个整数是不是2的整数次方。
思路:一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他所有位都是0。把这个整数与这个整数减去1之后进行与运算,那么这个整数当中唯一的1会变为0,这个整数也变为0。
代码:
#include "stdio.h"
#include <iostream>
using namespace std;
bool is2(int n)
{
return !(n&(n - 1));
}
int main()
{
bool b = is2(2);
cout << b << endl;
bool c = is2(3);
cout << c << endl;
getchar();
return 0;
}
相关题目2:输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。
思路:第一步求这两个数的异或运算,将异或运算结果存起来;第二步统计这个运算结果当中1的位数。
代码:
#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include <cstdlib>
int count(int m, int n)
{
int t, count = 0;
t = m^n; //两个数异或
while (t) //统计异或结果中的1的个数
{
count++;
t = t&(t - 1);
}
return count;
}
int main()
{
int num1=0, num2=0, ret = 0;
printf("请输入两个整数:");
scanf("%d %d", &num1,&num2);
ret = count(num1, num2);
printf("改变%d的二进制表示中的%d位才能得到%d\n", num1, ret, num2);
system("pause");
return 0;
}