题目类型: 素数个数统计
题目要求: 统计n以内的素数个数
- public class PrimeNumber1 {
-
- public static void main(String[] args) {
- //打印100以内的素数个数(预计结果为25)
- System.out.println("暴力算法统计素数个数为"+bf(100));
- //测试结果确实为25
- }
-
- /**
- * 使用暴力算法统计素数个数
- * @param n 统计素数边界值
- * @return 返回int型的素数个数
- */
- public static int bf(int n) {
- //统计素数个数的计数器
- int count = 0;
- //外层for循环遍历(其时间复杂度为n)
- for (int i = 2; i < n; i++) {
- //使用三元运算符: 判断数字i是否为素数, 若是素数(值为false), count值加1, 否则保持不变
- // count += isPrime(i) ? 1 : 0;
- //算法改进后进行素数判断
- count += isPrime2(i) ? 1 : 0;
- }
- return count;
- }
-
- /**
- * 判断当前数字是否为素数 原版
- * @param x 整型自然数
- * @return 布尔型值true或者false
- */
- private static boolean isPrime(int x) {
- //内层for循环遍历(其时间复杂度为x)
- for (int i = 2; i < x; i++) {
- //判断x是否为素数(即判断x是否能够被i整除)
- if(x % i == 0) {
- //若能被整除, 则返回false
- return false;
- }
- }
- //若不能被整除, 则返回true
- return true;
- }
-
- /**
- * 判断当前数字是否为素数 改进版
- * 在第一版基础上降低算法时间复杂度
- * @param x 整型数字
- * @return 布尔型值true或者false
- */
- private static boolean isPrime2(int x) {
-
- /**
- * 问题: 使用暴力算法时, 总的时间复杂度为n+x, 执行效率太低
- * 改进思路:
- * i的取值范围其实没必要取到x, 实际上只需要取到根号下x即可;
- *
- * 为什么取到根号下x就可以了呢?
- * 假设x值为12, 那么12能被整除的组合因子有哪些呢?
- * 包括: 1*12 2*6 3*4 4*3 6*2 12*1
- * 我们发现, 前面三个跟后面三个的关系只是两个因子位置颠倒,
- * 也就是满足乘法交换律, 只要能被前三个组合中的两个因子整除,
- * 也一定能被后三个组合中的两个因子整除, 因此取到根号下x即可;
- * 这样不仅可以减少for循环次数, 而且时间复杂度也随之降低
- */
-
- //内层for循环遍历
- // for (int i = 2; i < x; i++) {
- //方式一: 使用Math.sqrt()函数开根号
- for (int i = 2; i <= Math.sqrt(x); i++) {
- //方式二: 使用i * i < x表示(作用相当于x开根号)
- // for (int i = 2; i * i <= x; i++) {
- //判断x是否为素数(即判断x是否能够被i整除)
- if(x % i == 0) {
- //若能被整除, 则返回false
- return false;
- }
- }
- //若不能被整除, 则返回true
- return true;
- }
-
- }