C语言实现《剑指offer》——10_二进制中1的个数(两种方法实现)

本篇是10_二进制中1的个数的C语言实现:

题目描述:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

本文采用两种方式实现,我称他们为normal方法surprise方法,他们的区别如下:

  1. normal使用的是循环移位,因为考虑到有符号数负数右移,左边空位补1的情况,因此定义了一个无符号的flag初始化为1,并让flag循环左移,与输入相与,便能得到输入中1的个数。这种办法属于常规操作,不管输入的int中有多少个1,都要循环32次
  2. surprise的方法能把循环次数减少到"输入int中1的个数"次
    surprise使用的是n和n-1的与的值再赋给n,直到n的值为0时结束,因为每次“减1再与”的操作都能在原输入中干掉一个1,直到干完为止(读者可以用n的二进制为1100试试)

代码如下:

//normal法实现
#include 

int 
NumberOf1InBinary(int n)
{
	int count = 0;
	unsigned int flag = 1;			//flag是一个无符号数字,左移右移都是添0
	while(flag)
	{
		if (n & flag)
			count++;
		flag = flag << 1;
	}
	return count;
}

int 
main(int argc, char* argv[])
{
	freopen("sample.txt","r",stdin);
	int n;
	while(scanf("%d",&n) != EOF)
	{
		printf("%d\n",NumberOf1InBinary(n));
	}
	return 0;
}
//surprise法实现
#include 

int 
NumberOf1InBinary(int n)
{
	int count = 0;
	while(n)
	{
		count++;
		n = n & (n - 1);			//该方法比下面注释掉的普通方法的优势在于:
	}								//普通方法要循环32次(flag的位数),优化方法循环次数等于1的个数
	/*
	int count = 0;
	unsigned int flag = 1;			//flag是一个无符号数字,左移右移都是添0
	while(flag)
	{
		if (n & flag)
			count++;
		flag = flag << 1;
	}
	*/
	return count;
}

int 
main(int argc, char* argv[])
{
	freopen("sample.txt","r",stdin);
	int n;
	while(scanf("%d",&n) != EOF)
	{
		printf("%d\n",NumberOf1InBinary(n));
	}
	return 0;
}

测试样例和更详细的题目描述,可以参考我的github:Matthew-Haonan的github.

持续更新,欢迎留言讨论。

你可能感兴趣的:(Coding,Interview)