素数 素数的定义 寻找素数的方法:试除法、埃氏筛法、(优化)欧拉筛法----Java(代码实现)

素数

素数的定义:

        素数也叫质数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做素数,否则就是合数(规定:1既不是质数也不是合数)。

寻找素数的方法:

试除法:

        解释:试除法由名字可以知道就是根据定义用 2 到 N - 1 的数一个一个试除,如果 N不能整除之间所有的数,那么它就是素数。这样从 2 试到 N - 1,显然时间复杂度很高,我们有没有方法可以降低一些时间复杂度?

代码实现如下:

public class Util {
    private Util() {

    }

   /**
     *
     * @param n 传进来的一个整数
     * @return boolean
     * @date 2023/8/5 13:24
     * @description 试除法(判断素数)
     */
    private static final int PRIME_START_NUM = 2;

    public static boolean primeCommon(int n) {
        if (n < PRIME_START_NUM) {
            return false;
        }
        // 这里用 i <= n / i 或 i * i <= n 比 i <= sqrt(n)要好
        for (int i = PRIME_START_NUM; i <= n / i; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

    @Contract(pure = true)
    public static int @NotNull [] primeRangeCommon(int n) {
        int[] prime = new int[n];
        for (int i = 2; i <= n; i++) {
            if (primeCommon(i)) {
                prime[i - PRIME_START_NUM] = i;
            }
        }
        int count = 0;
        for (int item : prime) {
            if (item != 0) {
                count++;
            }
        }
        int[] outPutPrime = new int[count];
        count = 0;
        for (int value : prime) {
            if (value != 0) {
                outPutPrime[count++] = value;
            }
        }
        return outPutPrime;
    }

}

埃氏筛法:

        解释:也是用于解决这类问题简单快速的方法,可以很快找到[2, n]中的所有素数,即从2开始寻找素数,每次找到一个素数后就将它的倍数全都过筛掉, 并将该素数存储到另一个数组中,连续循环,直至原始数组为null。

代码实现如下:

@Contract(pure = true)
    private static int @NotNull [] prime(int n) {
        // 声明一个计数器
        int count = 0;
        // 声明一个数组,用来存放素数
        int[] prime = new int[n];
        // 声明一个筛选数组 默认全false
        boolean[] st = new boolean[n];
        for (int i = PRIME_START_NUM; i <= n; i++) {
            // 如果过筛,放进素数数组
            if (!st[i - 1]) {
                prime[count++] = i;
                // 每找到一个素数后就将它的倍数全部筛选掉
                // 这里可以优化成 int j = i * i
                for (int j = PRIME_START_NUM * i; j <= n; j += i) {
                    st[j - 1] = true;
                }
            }
        }
        return prime;
    }

    @Contract(pure = true)
    public static int @NotNull [] primeRange(int n) {
        int count = 0;
        for (int prime : prime(n)) {
            if (prime != 0) {
                count++;
            }
        }
        int[] outPutPrime = new int[count];
        if (outPutPrime.length >= 0) {
            System.arraycopy(prime(n), 0, outPutPrime, 0, outPutPrime.length);
        }
        return outPutPrime;
    }

(优化)欧拉筛法:

        解释:埃氏筛法中,由于一个数有可能同时会是两个不同素数的倍数,即可能出现重复过筛(重复标记)的情况,即同一个数被过筛掉了不止一次,会浪费一部分资源。欧拉筛法就是在埃氏算法的逻辑之上多了一个判断的步骤,从而消去了这种重复过筛的情况,中心思路就是利用合数中的某一个因数过筛掉该合数本身,即利用已经求得的素数,第一环将区间内的数从小到大遍历,第二重环将已求知的素数进行升序遍历,将这个数和素数的乘积标记为合数。这时如果有一个数能被素数整除,立即跳出循环。

代码实现如下:

  @Contract(pure = true)
    private static int @NotNull [] primePlus(int n) {
        // 声明一个计数器
        int count = 0;
        // 声明一个数组,用来存放素数
        int[] prime = new int[n];
        // 声明一个筛选数组 默认全false
        boolean[] st = new boolean[n * n];
        for (int i = PRIME_START_NUM; i <= n; i++) {
            // 如果过筛,放进素数数组,
            if (!st[i]) {
                prime[count++] = i;
            }
            // 每找到一个素数后就将它的倍数全部筛选掉
            for (int j = 0; prime[j] <= n / i; j++) {
                st[prime[j] * i] = true;
                if (i % prime[j] == 0) {
                    break;
                }
            }
        }
        return prime;
    }

    @Contract(pure = true)
    public static int @NotNull [] primeRangePlus(int n) {
        int count = 0;
        for (int prime : primePlus(n)) {
            if (prime != 0) {
                count++;
            }
        }
        int[] outPutPrime = new int[count];
        if (outPutPrime.length >= 0) {
            System.arraycopy(primePlus(n), 0, outPutPrime, 0, outPutPrime.length);
        }
        return outPutPrime;
    }

    @Contract(pure = true)
    public static int @NotNull [] primeRangePlus(int n, int anotherN) {
        // 起始[2,n]范围内的所有素数
        int[] primeStart = primeRangePlus(n);
        // 结束[2,anotherN]范围内的所有素数
        int[] primeEnd = primeRangePlus(anotherN);
        // 输出[n,anotherN]范围内的所有素数
        int[] outPutPrime = new int[primeEnd.length - primeStart.length];
        Arrays.fill(outPutPrime, primeEnd[primeStart.length]);
        return outPutPrime;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值