
一、题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的 N ( N 为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有4个正整数:2,5,6,13,如果将5和6分为一组中只能得到一组“素数伴侣”,而将2和5、6和13编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。
有一个正偶数 n ,表示待挑选的自然数的个数。后面给出 n 个具体的数字。
输出一个整数 K ,表示你求得的“最佳方案”组成“素数伴侣”的对数。
数据范围: 1≤n≤100,输入的数据大小满足 2≤val≤30000 
二、输入描述
- 输入一个正偶数 n
- 输入 n 个整数
三、输出描述
求得的“最佳方案”组成“素数伴侣”的对数。
四、解题思路
- 从输入中读取一个正偶数n;
- 创建一个长度为n的整数数组nums,用于存储n个整数;
- 循环读取n个整数,将其存储到nums数组中;
- 创建两个列表,一个用于存储偶数,一个用于存储奇数;遍历nums数组,将偶数存储到偶数列表(evens)中,将奇数存储到奇数列表(odds)中;
- 创建一个长度为偶数列表evens的整数数组evenMatch,用于存储每个偶数的伴侣奇数;初始化count为0,用于记录素数伴侣的对数;
- 对每个奇数进行匹配操作;遍历奇数列表odds,依次取出一个奇数odd; 
  - 创建一个布尔数组match,用于记录每个偶数是否已被占用;初始化为false;
- 使用递归函数find()进行偶数的匹配;在find()函数中,依次遍历偶数列表evens,取出一个偶数even; 
    - 如果该偶数未被占用且偶数与奇数的和是素数(调用isPrime()函数判断),则将该奇数设置为偶数的伴侣,即evenMatch[i] = odd,并将该偶数设置为已占用(match[i] = true);
- 如果该偶数已被其他奇数占用,则递归调用find()函数,寻找其他可匹配的偶数;
 
- 如果能找到素数匹配,则count加1;
 
- 输出count,即最佳方案组成素数伴侣的对数;
五、Java算法源码
public static void main(String [] args){
    Scanner in = new Scanner(System.in);
    while(in.hasNext()){
        int n = in.nextInt();
        //定义数组
        int [] nums = new int[n];
        for(int i = 0;i < n ;i++){
            nums[i] = in.nextInt();
        }
        //分装为 偶数数组 和奇数数组
        List<Integer> evens = new ArrayList<>();
        List<Integer> odds = new ArrayList<>();
        for(int num:nums){
            if(num % 2 ==0){
                evens.add(num);
            }else{
                odds.add(num);
            }
        }
        //偶数的伴侣
        int [] evenMatch = new int[evens.size()];
        int count = 0;
        //用每个奇数 尝试匹配偶数
        for(int i = 0;i < odds.size();i++){
            int odd = odds.get(i);
            //偶数是否被占用
            boolean [] match = new boolean[evens.size()];
            if(find(odd,evens,evenMatch,match)){
                count++;
            }
        }
        System.out.println(count);
    }
}
private static boolean find(int odd,List<Integer> evens,int [] evenMatch,boolean [] match){
    for(int i = 0;i < evens.size();i++){
        int even = evens.get(i);
        //挨个匹配 偶数
        if(!match[i] && isPrime(even + odd)){
            //这个偶数没有被占用 且 偶数+奇数 为素数
            //增加访问标记
            match[i] = true;
            if(evenMatch[i] == 0 || find(evenMatch[i],evens,evenMatch,match)){
                //偶数索引对应的 素数为0 说明没有被其他素数占用 或者可以找到素数
                //则将该奇数设置为偶数的伴侣
                evenMatch[i] = odd;
                //找到了素数
                return true;
            }
        }
    }
    return false;
}
private static boolean isPrime(int x){
    if(x == 1){
        return false;
    }
    for(int i = 2; i <= (int)Math.sqrt(x);i++){
        if(x % i == 0){
            return false;
        }
    }
    return true;
}
六、效果展示

🏆下一篇:华为OD机试真题 Java 实现【跳房子II】【2023 B卷 100分】,附详细解题思路
🏆本文收录于,华为OD机试(JAVA)(2022&2023)
本专栏包含了最新最全的2023年华为OD机试真题,有详细的分析和Java解答。已帮助1000+同学顺利通过OD机考。专栏会持续更新,每天在线答疑。




















