《剑指Offer》面试题10:二进制中1的个数

《剑指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;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值