素数的相关算法

本文介绍了两种求一定范围内素数的Java算法,包括一个标记数组法和一个优化后的重复标记法。还提到针对单个数的素性判断算法。推荐阅读关于素数筛的详细总结文章以深入了解原理。

今天在做pat的算法题时,遇到一道算法:写出一定范围内的素数想了半天没有思路,后来用的方法也是错的,只能上网搜索文章最后总结了相关的算法

当问题是一定范围内的素数时

遇到这种问题一般有两种解法,我会直接给大家提供优化过的算法

算法一:

算法如下:

 public static void prime1(int nMax){

        //arr数组是一个标记数组其长度为 :范围最大值 + 1;
        int[] arr = new int[nMax + 1];
        //该数组是存储运算结果。
        int[] res = new int[nMax / 2];
        res[0] = 1;
        res[1] = 2;
        //这里的k从2开始。
        int k = 2;

        for(int i = 3;i <= nMax;i += 2){
            arr[i + 1] = 1;
            if(arr[i] == 0){
                res[k++] = i;
                for(int j = i;j * i <= nMax;j++){
                    arr[i * j] = 1;
                }
            }
        }

    }
算法二:

算法如下:

public static void prime2(int nMax){
        //arr数组是一个标记数组其长度为 :范围最大值 + 1;
        int[] arr = new int[nMax + 1];
        //该数组是存储运算结果。
        int[] res = new int[nMax / 2];
        //标记所有偶数并排除2;
        arr[0] = 1;
        for(int i = 4;i <= nMax;i += 2){
            arr[i] = 1;
        }
        //从sqrt对重复标记进行优化,从只对奇数进行判断做重复标记优化。从j的起始值设置为i减少重复标记
        for(int i = 3;i <= Math.sqrt(nMax);i += 2){
            arr[i + 1] = 1;
            if(arr[i] == 0){
                for(int j = i;j * i <= nMax;j++){
                    arr[j * i] = 1;
                }
            }

        }
        int k = 0;

        for(int i = 0;i < arr.length;i++){
            if(arr[i] == 0){
                res[k++] = i;
            }
        }

    }

两种算法的比较:

这个程序后面补了一个循环,和之前的程序相比,效率似乎反而降低了。之前的程序,在一遍循环中完成标记和存储两个任务,而这个程序需要三个循环。但由于该循环使用的条件是开方所以该程序在数据量极大的情况下可能可以有效减少运行时间。

注意:java的数组不能长度超过2^32 - 1

当问题是判断单个数是否为素数;

遇到这种情况直接使用如下算法:

public static boolean primeSingle(int arg){

        if(arg == 1 || arg == 2)return true;
        if(arg % 2 == 0)return false;


        for(int i = 3; i <= Math.sqrt(arg);i += 2){
            if(arg % i == 0)return false;
        }

        return true;

    }

这些代码看起来都很简单,但其都是经过多次优化的代码,所以要了解其原理最好找一篇相关文章看看,我推荐这篇文章:

1、素数筛(这应该是最全的总结了,四种基本方法,7种优化方法)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值