题目
小C对排列很感兴趣,她想知道有多少个长度为n的排列满足任意两个相邻元素之和都不是素数。排列定义为一个长度为n的数组,其中包含从1到n的所有整数,每个数字恰好出现一次。
题目理解
-
排列的定义:
- 排列是一个长度为
n的数组,其中包含从1到n的所有整数,每个数字恰好出现一次。 - 例如,当
n = 3时,可能的排列有[1, 2, 3],[1, 3, 2],[2, 1, 3],[2, 3, 1],[3, 1, 2],[3, 2, 1]。
- 排列是一个长度为
-
相邻元素之和:
- 对于一个排列,任意两个相邻元素之和不能是素数。
- 例如,在排列
[1, 2, 3]中,相邻元素之和为1 + 2 = 3和2 + 3 = 5,其中3和5都是素数,因此这个排列不符合条件。
-
目标:
- 需要计算出所有满足条件的排列的数量。
解题思路
-
生成所有排列:
- 首先,生成从
1到n的所有排列。可以使用递归或迭代的方式来生成所有排列。
- 首先,生成从
-
检查相邻元素之和:
- 对于每一个生成的排列,检查相邻元素之和是否为素数。如果某个排列中所有相邻元素之和都不是素数,则该排列符合条件。
-
计数符合条件的排列:
- 统计所有符合条件的排列的数量,并返回结果。
数据结构与算法选择
-
数据结构:
- 使用
List<List<Integer>>来存储所有生成的排列。 - 使用
List<Integer>来存储单个排列。
- 使用
-
算法:
- 排列生成:使用递归或迭代的方式生成所有排列。
- 素数检查:编写一个函数
isPrime来判断一个数是否为素数。 - 条件检查:遍历每个排列,检查相邻元素之和是否为素数。
代码思路
- 生成所有排列:通过递归函数
result生成从1到n的所有排列,并将这些排列存储在List<List<Integer>> list中。 - 检查相邻元素之和是否为素数:遍历每一个排列,检查相邻元素之和是否为素数。如果某个排列中所有相邻元素之和都不是素数,则计数器
count加一。 - 返回结果:最终返回满足条件的排列数量。
代码
import java.util.ArrayList;
import java.util.List;
public class Main {
public static int solution(int n) {
// 排列的基础上更近一步加一点东西
List<List<Integer>> list = new ArrayList<>();
int [] nums = new int[n];
for(int i = 0; i < n; i++){
nums[i] = i + 1;
}
result(nums, 0,list);
//进行判断
int count = 0;
for(List<Integer> set : list){
int flag = 0;
for(int i = 0; i < set.size() - 1; i++){
if( isPrime( set.get(i) + set.get(i + 1)) ){
flag = 1;
break;
}
}
if(flag == 0) count ++;
}
return count;
}
//首先建立一个递归函数求解所有的情况
public static void result(int nums[], int start, List<List<Integer>>list){
//首先设置出口
if(start == nums.length - 1){
List<Integer> subsets = new ArrayList<>();
for(int target : nums){
subsets.add(target);
}
list.add(new ArrayList<>(subsets));
}
// 进行递归求解
for(int i = start; i < nums.length; i++){
// 进行交换
int temp = nums[i];
nums[i] = nums[start];
nums[start] = temp;
//进行递归
result(nums, start + 1, list);
//进行回溯,交换回原来的样子
temp = nums[i];
nums[i] = nums[start];
nums[start] = temp;
}
}
public static boolean isPrime(int n){
if(n <= 1) return false;
if(n == 2) return true;
for(int i = 2; i <= Math.sqrt(n); i++){
if(n % i == 0) return false;
}
return true;
}
public static void main(String[] args) {
System.out.println(solution(5) == 4);
System.out.println(solution(3) == 0);
System.out.println(solution(6) == 24);
}
}
代码分析
-
生成排列:
- 你使用了递归的方式来生成所有排列。通过交换数组中的元素来生成不同的排列,并在递归结束后进行回溯,恢复数组的状态。
- 这种方法是经典的排列生成方法,适用于较小的
n值。
-
检查素数:
- 你使用了
isPrime函数来判断一个数是否为素数。这个函数的实现是正确的,通过从2到sqrt(n)的范围内检查是否有因子来判断素数。
- 你使用了
-
主函数:
- 在
main函数中,你测试了几个样例,确保代码的正确性。
- 在