leetcode
leetcode 151 ~ 200
计数质数

计数质数

难度:

标签:

题目描述

给定整数 n ,返回 所有小于非负整数 n 的质数的数量

 

示例 1:

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

示例 2:

输入:n = 0
输出:0

示例 3:

输入:n = 1
输出:0

 

提示:

  • 0 <= n <= 5 * 106

代码结果

运行时间: 54 ms, 内存: 16.2 MB


/*
 * 思路:
 * 使用Java Stream和埃拉托斯特尼筛选法来计算质数数量。
 * 我们先生成一个从2到n-1的IntStream,然后过滤掉所有非质数。
 * 最后,返回过滤后元素的数量。
 */
import java.util.stream.IntStream;
 
public class CountPrimesStream {
    public int countPrimes(int n) {
        if (n <= 2) return 0;
        boolean[] isPrime = new boolean[n];
        for (int i = 2; i < n; i++) isPrime[i] = true;
        for (int i = 2; i * i < n; i++) {
            if (isPrime[i]) {
                for (int j = i * i; j < n; j += i) {
                    isPrime[j] = false;
                }
            }
        }
        return (int) IntStream.range(2, n).filter(i -> isPrime[i]).count();
    }
}

解释

方法:

此题解采用了经典的埃拉托斯特尼筛法(Sieve of Eratosthenes)来寻找所有小于非负整数 n 的质数。首先,算法创建一个布尔数组 isNumPrimes 来跟踪每个数是否为质数,初始化时假设所有数都是质数。接着,通过遍历2到n的每个数,如果发现一个数i是质数(isNumPrimes[i]为True),则将i的所有倍数设置为非质数(False),从而筛选掉非质数。这里需要注意的是,筛选从i*i开始,因为小于i*i的倍数在之前已经被筛选过了。最终,数组中为True的位置表示该位置的索引是质数,通过计数这些位置得到小于n的所有质数的数量。

时间复杂度:

O(n log log n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在筛法中,对于每个质数i,筛选开始于i*i而不是2*i或i+i?
在筛选算法中,当我们确定一个数i是质数时,我们需要筛除所有i的倍数,因为它们不是质数。如果我们从2*i开始筛选(也就是i+i),我们会重复筛除那些已经在处理更小的质数时被筛除的数。例如,当i=5时,10已经在处理i=2时被筛除。从i*i开始筛选可以避免这种重复,因为i的所有较小倍数(例如k*i,其中k
🦆
在大于平方根n的数字上,算法是否还需要检查其是否为质数?
在执行埃拉托斯特尼筛法时,实际上只需要考虑到n的平方根为止。因为如果n不是质数,并且它有一个因子大于其平方根,则其对应的另一个因子必定小于平方根。因此,如果在到达n的平方根时还未将数筛出,则之后的数无需继续检查,它们会自然保留为质数,或者在处理小于平方根的质数时已经被筛除。
🦆
给定初始化时布尔数组isNumPrimes的所有值都设为True,这种做法对空间复杂度有何影响?
将布尔数组isNumPrimes的所有值初始化为True意味着我们在开始筛选之前假定所有数都是质数。这种初始化策略是必要的,因为它定义了筛选的起始状态。这种做法导致的空间复杂度是O(n),因为我们需要一个与输入大小n相对应的布尔数组来存储每个数的状态。虽然这增加了算法的空间需求,但这是实现埃拉托斯特尼筛法所必须的,以确保能有效地筛选出非质数。

相关问题

丑数

丑数 就是只包含质因数 235 的正整数。

给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false

 

示例 1:

输入:n = 6
输出:true
解释:6 = 2 × 3

示例 2:

输入:n = 1
输出:true
解释:1 没有质因数,因此它的全部质因数是 {2, 3, 5} 的空集。习惯上将其视作第一个丑数。

示例 3:

输入:n = 14
输出:false
解释:14 不是丑数,因为它包含了另外一个质因数 7 

 

提示:

  • -231 <= n <= 231 - 1

丑数 II

给你一个整数 n ,请你找出并返回第 n丑数

丑数 就是质因子只包含 23 和 5 的正整数。

 

示例 1:

输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。

示例 2:

输入:n = 1
输出:1
解释:1 通常被视为丑数。

 

提示:

  • 1 <= n <= 1690

完全平方数

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,14916 都是完全平方数,而 311 不是。

 

示例 1:

输入:n = 12
输出:3 
解释:12 = 4 + 4 + 4

示例 2:

输入:n = 13
输出:2
解释:13 = 4 + 9
 

提示:

  • 1 <= n <= 104