LeetCode-204-计数质数

LeetCode-204-计数质数

题目来源:LeetCode-探索初级算法-数学-计数质数


题意描述: 统计所有小于非负整数 n 的质数的数量。


输入输出示例:

输入: 10
输出: 4
解释: 小于 10 的质数一共有 4, 它们是 2, 3, 5, 7

解题思路:

Bob:你可知道茴香豆的茴字有几种写法 ?
Alice: ヾ(。ꏿ﹏ꏿ)ノ゙,你说啥,这和质数有啥关系啊 ?你脑子瓦特了 ?
Bob: ┓( ´∀` )┏ 好吧,茴香豆的茴字有好几种写法,求解素数的程序也有好几种写法,这里面考的就是其中一种,筛法。
Alice: 你直接了当的说不就得了,不就是筛法求素数吗?
Bob: 啊,原来你会写啊。
Alice: 我不会,你来写,我给你 code review, ヾ(◍°∇°◍)ノ゙
Bob: 好。

求解素数的第一种方法就是按照定义来:

质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。-百度百科。

程序是这样子的:

bool isPrime(int x){
	if(x == 2 || x == 3 || x == 5 || x == 7){
		return true;
	}
	if(x <= 1 || x % 2 == 0){
		return false;
	}
	int bound = int(sqrt(x));
	for(int i=3; i<=bound; i+=2){
		if(x % i == 0){
			return false;
		}
	}
	return true;	
}

Alice: 等一下,你的代码怎么写的这么奇怪???不应该这么写吗 ?

bool isPrimeByAlice(int x){
	if(x < 2){
		return false;
	}else{
		for(int i=2; i<=x-1; i++){
			if(x % i == 0){
				return false;
			}
		}
	}
	return true;
}

Bob: 你听我解释啊,不是你想的那样的 !(ΩДΩ) 我也是按照定义法去判断一个数是不是素数的,只是优化了一下,减少了计算步骤。对于小于 9 的素数直接判断,对于大于 9的素数 X 用从 3 开始的奇数 到 根号 X 一个一个整除的。
Alice: 为什么算到 根号 X 而不是 X-1 啊?
Bob: 因为乘法具有交换性。举个例子 12 = 2 * 6 , 12 = 6 * 2 我们算到 12 被 2 整除就知道12 不是素数了,不用再去算12 能不能被6整除了。那么最少算到哪里好呢? 算到根号12, 大概就是 3.464,最多算到 4, 因为4 * 4 = 16 > 12 了就。对于素数,像 11 也是这样的,算到根号 x 就好了。
Alice: 原来是这样啊,的确快了一些,少了一些计算步骤。 除了2,所有的素数都是都是奇数,奇数不可能被偶数整除,所以只判断了从3开始的奇数。
Bob: 对,就是这样的。
Alice: 你继续讲筛法吧。
Bob: 先来看这个图,一图胜千言。
筛法
Bob: 可以这样理解,素数的所有倍数都不是素数,排除法把所有不是素数的去掉剩下的就是素数了。这也是为什么叫筛法的原因,沙里淘金,离开的总是有原因的吧。
Alice: 净扯些没用的,代码呢 ??

bool isPrimeShai(int x){
	int flags[100001];
	for(int i=0; i<=100000; ++i){
		flags[i] = 1;
	}
	for(int i=2; i<=x; ++i){
		if(flags[i] == 1){
			for(int j=i*2; j<=x; j+=i){
				flags[j] = 0;
			}
		}
	}
	return flags[x] == 1;
}

Bob: 这是C++ 版本的,没有用vector,所以没有动态数组,只能判断10万之内的素数。
Alice: 那我再写个Python。

def isPrime(number):
    flags = [1 for z in range(0, number + 1)]
    for x in range(2, number + 1):
        if flags[x] == 1:
            for z in range(x * 2, number + 1, x):
                flags[z] = 0
    return flags[x] == 1

Bob: ヾ(◍°∇°◍)ノ゙厉害呀。
Alice: 有空把C++还有Java 带“动态数字的”筛法补上。
Bob: ┓ ( ´∀` ) ┏,你叫我补上,我就补上,那岂不是很没有面子。
Alice: 嘿!!(’∇’)シ┳━┳


代码:

class Solution:
    def countPrimes(self, n: int) -> int:
        // 使用筛法求素数的方法求解
        cnt = 0 
        // 记录 1 到 N 的素数的个数 
        flags = [1 for x in range(0, n+1)]
        // 用于标记一系列数字是否是素数, x 是素数的时候, flags[x] == 1。flags初始化为全1的数组即首先假设所有数字都是素数。
        for x in range(2, n):
            //2开始遍历,因为2是一个真正的素数。
            if flags[x] == 1:
                cnt += 1
                // 如果有一个素数,计数加一,然后
                for z in range(2*x, len(flags), x):
                    // 这个素数的所有倍数都不是素数,注意看循环。
                    flags[z] = 0
        return cnt
        // 最后flags里面标记为1的位置对应的数都是素数,cnt记录了素数的个数。
    

易错点:

  • 毋庸置疑,定义法会超时。

总结:


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值