质数排列
难度:
标签:
题目描述
代码结果
运行时间: 24 ms, 内存: 16.0 MB
// Solution for leetcode problem using Java Streams
// The task is to count the number of permutations of numbers from 1 to n where all prime numbers are at prime indices.
// A prime index is 1-based. We need to return the result modulo 10^9 + 7.
import java.util.stream.IntStream;
public class PrimeArrangementStream {
private static final int MOD = 1000000007;
// Function to check if a number is prime
private static boolean isPrime(int num) {
if (num <= 1) return false;
if (num == 2 || num == 3) return true;
if (num % 2 == 0 || num % 3 == 0) return false;
for (int i = 5; i * i <= num; i += 6) {
if (num % i == 0 || num % (i + 2) == 0) return false;
}
return true;
}
// Function to count primes up to n
private static int countPrimes(int n) {
return (int) IntStream.rangeClosed(1, n).filter(PrimeArrangementStream::isPrime).count();
}
// Function to calculate factorial modulo MOD
private static long factorial(int num) {
return IntStream.rangeClosed(2, num).asLongStream().reduce(1, (a, b) -> (a * b) % MOD);
}
public static int numPrimeArrangements(int n) {
int primeCount = countPrimes(n);
int nonPrimeCount = n - primeCount;
long primeFactorial = factorial(primeCount);
long nonPrimeFactorial = factorial(nonPrimeCount);
return (int) ((primeFactorial * nonPrimeFactorial) % MOD);
}
public static void main(String[] args) {
System.out.println(numPrimeArrangements(5)); // Output: 12
System.out.println(numPrimeArrangements(100)); // Output: 682289015
}
}
解释
方法:
题解的核心思想是将1到n的数字分为质数和非质数两部分,然后分别在质数的索引位置放置所有质数,非质数索引位置放置所有非质数。首先,算法通过遍历从2到n的所有数字,使用试除法判断每个数是否为质数。如果一个数是质数,质数计数器p递增;如果不是,非质数计数器c递增。之后,为了计算所有可能的排列方案,算法计算p个质数可以有多少种排列方式,即计算p的阶乘。同理,也计算非质数的c个数字的阶乘。最后,将这两个阶乘相乘得到总排列数,由于结果可能非常大,最后结果对10^9 + 7取模。
时间复杂度:
O(n√n)
空间复杂度:
O(1)
代码细节讲解
🦆
在判断一个数是否为质数时,你是如何确保在找到第一个使得i % j == 0的j后立即停止循环的?
▷🦆
在计算非质数数量时,为什么会有一个修正操作 `p -= 1`?这是否意味着在计算过程中有可能会错误地将某些数计为质数?
▷🦆
在计算阶乘部分,你采用了直接的连乘方式,这种方法在n较大时有没有可能导致整数溢出?如果有,如何避免?
▷🦆
在最终求解时,你是如何处理阶乘结果可能非常大的情况的?是否在每次乘法操作后就进行了模运算?
▷