C语言实验过程化记录-2

最近在力扣上刷了一道题,不是很难,过来挑战把思路讲出来。

 后面给出的示例如下:

 接下来将结合个人理解和官方题解(作者:力扣官方题解
链接:https://leetcode.cn/problems/prime-number-of-set-bits-in-binary-representation/solutions/1389365/er-jin-zhi-biao-shi-zhong-zhi-shu-ge-ji-jy35g/
来源:力扣(LeetCode))
,介绍两种解题思路。

思路一 数学+位运算

本题有两个关键点:分析出整型数字的二进制形式,以及判断数字的二进制里的1的总数是否为质数。

首先解决第一个关键。将十进制的整型数字转化为二进制。这里有两种思路。第一种是基础思路,就是不断将原数字%2(二进制满二进一,这里判断二进制每一位上是0还是1),判断余数是否为1。

第二种转化二进制思路是用“ n&(n-1) ” 。由于每次n-1就让原来n上最低位的1被消去,n&(n-1)后又成功将消去位以右的二进制位,将它们都化为0,实现了每次消去二进制最右边一个1的功能;最终实现统计位1的个数。用例子解释如下:

再解决第二个关键:判断质数。判断质数,有两种思路:

  1. 利用一个i 变量遍历从2到被求数之间的数并与之相除,没有出现整除即为质数。
  2. 利用i 变量遍历从2到sqrt(被求数)之间的数并与之相除,没有出现整除即为质数。

 第一种老生常谈且基础,运用第二种思路写出来的代码更加高效。

综上,可以写出程序如下:

int isPrime(int left, int (* Func_count)(int))
{
	int num = (*Func_count)(left);//num接受对一个二进制数里1的计数
	if (num < 2)
		return 0;//0或1都不是质数
	else {
		for (int i = 2; i * i <= num; i++)
			//判断质数:用2至根号下num之间的数字除原数,如果出现余数为0,则不是质数
		{
			if (num % i == 0)
				return 0;
		}
	}
	return 1;//排除上述两只情况,其他都是质数
}
int Func_count(int num)//基础方法,将原数转换为二进制数,并统计1的个数
{
	int count = 0;
	while (num != 0)
	{
		if (num % 2 == 1)
			count++;
		num /= 2;
	}
	return count;
}
int main()
{
	int left = 0, right = 0;
	int sum = 0;
	scanf("%d %d", &left, &right);
	while(left<=right)
	{
		if (isPrime(left, Func_count))//0-不是质数,1-是质数
			sum++;
		left++;
	}
	printf("%d\n", sum);
	return 0;
}

 这个程序主要是思路比较清晰。

思路二 质数判断优化-按位与

按位与&:

在两个数都为int型的大前提下,判断两个数的二进制(补码的形式)每位的01相同情况。只有对应的两个二进制位都为1时,才得1;否则为0 。

比如,判断 10&3 的结果,思路如下:

 根据按位与的功能,我们再来思考这道题。

 题里有提到左右两个数的取值范围最高到10^6为止,而10^6 < 2^20,可推知本题判断的“二进制位1的总计数”的质数范围也就在0~20之间,20内的质数一共有:2,3,5,7,11,13,17,19。所以我们可以将它们储存在一个新的二进制里——

mask=665772=10100010100010101100

 假设left至right之间有一个数x,它的二进制位1的总数为c,就可以用(mask)&(2^c)的方式来判断c在二进制中的位置是否是在质数的位置:

int Func_count(int num)//二进制位1统计的第二种方法
{
	int count = 0;
	while (num)
	{
		num &= num - 1;
		count++;
	}
	return count;
}
int main()
{
	int left = 0, right = 0, sum = 0;
	scanf("%d %d", &left, &right);
	while (left <= right)
	{
		if (1 << Func_count(left) & 665772)
			//先将1左移统计数count的位数,即将返回值放在二进制的相应位数上
			sum++;
		left++;
	}
	printf("sum = %d\n", sum);
	return 0;
}

总结

这道题里,对于判断二进制位1的两种方法,操作符的方法还需多多回顾,以便于掌握。同时对于质数判断的优化方法也要多加理解,一方面能开拓思路,另一方面可以加深对本题的认识。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值