• 【每日一题】1175. 质数排列


    感觉这方面的自己练的有点少。
    做一个总结。。。

    204. 计数质数
    题目:
    给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。
    质数的定义:在大于 1 的自然数中,除了 1 和它本身以外不再有其他因数的自然数。

    • 枚举
    class Solution {
        public int countPrimes(int n) {
            int ans = 0;
            for (int i = 2; i < n; ++i) {
                ans += isPrime(i) ? 1 : 0;
            }
            return ans;
        }
    
        public boolean isPrime(int x) {
            for (int i = 2; i * i <= x; ++i) {
                if (x % i == 0) {
                    return false;
                }
            }
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    如果一个数A是质数,那么2A,3A,…,n*A一定不是质数
    所以可以在[1,n]这个范围内,从最开始的2,3就开始给质数后面的数进行做初始化操作!

    class Solution {
        public int countPrimes(int n) {
            int[] isPrime = new int[n];
            //填充isPrime数组的每个元素都是1
            Arrays.fill(isPrime, 1);
            int count = 0;
            for (int i = 2; i < n; ++i) {
                if (isPrime[i] == 1) {
                    /**
                     * 说明i是质数!
                     */
                    count++;
                    if ((long) i * i < n) {
                        for (int j = i * i; j < n; j += i) {
                            isPrime[j] = 0;
                        }
                    }
                }
            }
            return count;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    这题还有更好的筛法——线性筛,但不属于笔试/面试范畴,不需要掌握。

    • 线性筛
    class Solution {
        public int countPrimes(int n) {
            List<Integer> primes = new ArrayList<Integer>();
            int[] isPrime = new int[n];
            Arrays.fill(isPrime, 1);
            for (int i = 2; i < n; ++i) {
                if (isPrime[i] == 1) {
                    primes.add(i);
                }
                for (int j = 0; j < primes.size() && i * primes.get(j) < n; ++j) {
                    isPrime[i * primes.get(j)] = 0;
                    if (i % primes.get(j) == 0) {
                        break;
                    }
                }
            }
            return primes.size();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    1175. 质数排列
    [数学 + 质数 + 阶乘]
    参考题解:https://leetcode.cn/problems/prime-arrangements/solution/1175-zhi-shu-pai-lie-java-100-by-wa-pian-bo17/

    • [1,n]一共有多少个质数
    • ans == 质数!* 非质数!

    根据题意,可将问题转换为求 n 以内的质数个数,记为 a,同时可得非质数个数为 b = n - a
    质数的放置方案数为 a!,而非质数的放置方案数为 b!,根据「乘法原理」总的放置方案数为 a!×b!

    class Solution {
    	int mod = (int) 1e9 + 7;
    
    	public int numPrimeArrangements(int n) {
    		int prime = 0;
    		for (int i = 1; i <= n; i++) {
    			if (isPrime(i)) {
    				prime++;
    			}
    		}
    		long ans = factorial(prime);
    		ans *= factorial(n - prime);
    		return (int) (ans % mod);
    	}
    
    	//阶乘
    	private long factorial(int num) {
    		long ans = 1;
    		for (int i = 1; i <= num; i++) {
    			ans *= (long) i;
    			ans %= mod;
    		}
    		return ans;
    	}
    
    	private boolean isPrime(int num) {
    		if (num == 2) {
    			return true;
    		}
    		if (num == 1 || num % 2 == 0) {
    			return false;
    		}
    		for (int i = 3; i * i <= num; i += 2) {
    			if (num % i == 0 || i * i == num) {
    				return false;
    			}
    		}
    		return true;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    参考:https://leetcode.cn/problems/prime-arrangements/solution/by-ac_oier-t3lk/
    打表 + 二分 + 数学
    可以通过「打表」的方式将 100 以内的质数预处理到数组 list 中,对于每个 n 而言,我们找到第一个满足「值小于等于 n」的位置,从而得知 n 范围以内的质数个数。

    class Solution {
        static int MOD = (int)1e9+7;
        static List<Integer> list = new ArrayList<>();
        static {
            for (int i = 2; i <= 100; i++) {
                boolean ok = true;
                for (int j = 2; j * j <= i; j++) {
                    if (i % j == 0) ok = false;
                }
                if (ok) list.add(i);
            }
        }
        public int numPrimeArrangements(int n) {
            int l = 0, r = list.size() - 1;
            while (l < r) {
                int mid = l + r + 1 >> 1;
                if (list.get(mid) <= n) l = mid;
                else r = mid - 1;
            }
            int a = r + 1, b = n - a;
            long ans = 1;
            for (int i = b; i > 1; i--) ans = ans * i % MOD ;
            for (int i = a; i > 1; i--) ans = ans * i % MOD ;
            return (int)ans;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    MybatisPlus——全网配置最全的代码生成器
    带你深入了解Web3开发者堆栈
    Idea设置
    HTML期末大学生网页设计作业——奇恩动漫HTML (1页面) HTML+CSS+JS网页设计期末课程大作业
    Flink Checkpoint
    helm部署gitlab-runner问题解决
    【PyTorch】基础知识及常用操作
    TCP协议之《乱序队列Out-Of-Order》
    计算机网络实验第五次 11月8日
    C语言,数据在内存中的存储。——保姆级教学
  • 原文地址:https://blog.csdn.net/m0_58058653/article/details/125546969