题解 | #查找组成一个偶数最接近的两个素数#

查找组成一个偶数最接近的两个素数

http://www.nowcoder.com/practice/f8538f9ae3f1484fb137789dec6eedb9

描述

题目描述

任意一个偶数(大于2)都可以由2个素数组成,组成偶数的2个素数有很多种情况,本题目要求输出组成指定偶数的两个素数差值最小的素数对。

示例

输入:
20
输出:
7
13

知识点:穷举,贪心,数组,基础数学

难度:⭐⭐⭐


题解

方法一:穷举

解题思路

对于一个数字,我们可以从2遍历到n,寻找两个加数都是素数的情况,然后比较素数之间的差值,把要输出的变量更新为更小的差值及这两个变量,最后枚举完得到就是差值最小的两个素数。

算法流程

  • 从2开始穷举,直到num
  • 如果 isPrime(i) && isPrime(num - i)判断是否素数后,保存两数之差最小的两个元素

Java 版本代码如下:

import java.util.*;
 
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
        	int num = scanner.nextInt();
        	solution(num);
        }
    }

    private static void solution(int num) {
        int min = Integer.MAX_VALUE;
        int[] res = new int[2];
        // 从2开始穷举
        for(int i = 2; i < num; i++) {
            if(isPrime(i) && isPrime(num - i)) {
                // 保存最接近的两个素数
                if(Math.abs(num - i - i) < min) {
                    res[0] = i;
                    res[1] = num - i;
                    min = Math.abs(num - i - i);
                }
            }
        }
        System.out.println(res[0] + "\n" + res[1]);
    }
    // 判断是否素数
    private static boolean isPrime(int num) {
        for(int i = 2; i <= Math.sqrt(num); i++) {
            if(num % i == 0) {
                return false;
            }
        } 
        return true;
    }
}

复杂度分析

时间复杂度NNN\sqrt{N},外循环遍历N次,内循环遍历N\sqrt{N}

空间复杂度O(1),无需用到额外空间

方法二:穷举优化

图解

image-20211208165059799

解题思路:

采取从中间向两边枚举的方式,这样贪心的控制住两素数之差距离最小的这个限制

算法流程

  • 对于每个数字,从最接近的两个中位数开始处理判断是否素数
  • 如果两个组成偶数的数字都是素数,因为是从最接近的两个数开始枚举,因此一旦都是素数则输出并返回,得到结果

Java 版本代码如下:

import java.util.*;
 
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
        	int num = scanner.nextInt();
        	solution(num);
        }
    }

    private static void solution(int num) {
        //如num=10, 遍历:5,6,7,8
        // 从最接近的两个中位数开始处理判断
        for(int i = num / 2; i < num - 1; i++) {
            if(isPrime(i) && isPrime(num - i)) {
                System.out.println((num - i) + "\n" + i);
                return;
            }
        }
    }
    // 判断是否素数
    private static boolean isPrime(int num) {
        for(int i = 2; i <= Math.sqrt(num); i++) {
            if(num % i == 0) {
                return false;
            }
        } 
        return true;
    }
}

复杂度分析

时间复杂度NNN\sqrt{N},外循环最多遍历 N/2 次,内循环每个数最多是N\sqrt{N}

空间复杂度O(1),只用到常数级别的空间开销

全部评论
可以循环里面加个判断 if(i == 2 || i%2 == 0){ i++; } else{ i +=2; } 这样可以少循环几次,避免多次调用判定质数方法
1 回复 分享
发布于 2023-06-07 16:21 四川
穷举法可以在中间数向两边搜索,如果找到2个素数,这2个素数的差值肯定就是最小的,这样就不用继续循环搜索了
1 回复 分享
发布于 2023-02-05 22:37 广东
b * c = m 成立只能 一个数b在[1,a]区间上,另一个c在[a,m]区间上,a * a = m, a可以理解为平衡点,m能在小区间[1,a]里整除与否不用看大区间了,减少是素数情况下全遍历; eg: 非素数 5 * 20 = 100找到了5, 就不用看20 素数 17 只需要遍历小区间[2,4.123105625617661]中的整数就能判断是不是素数了 大概是这么个意思吧,具体可以网上找下严谨逻辑推理
点赞 回复 分享
发布于 2024-10-22 17:50 湖北
i <= Math.sqrt(num) 这个没看懂,为什么开根号?
点赞 回复 分享
发布于 2023-10-01 16:45 北京
写的真好
点赞 回复 分享
发布于 2022-07-07 17:23

相关推荐

不愿透露姓名的神秘牛友
07-11 11:24
大家还是用ai改吧,我心疼得要死,就当花钱买教训吧,人家直接拿完钱就跑路了
程序员小白条:简历修改700....神奇,又不是帮你面试,咋的,简历修改从双非变92了还是没实习变成有大厂实习了
点赞 评论 收藏
分享
07-14 12:29
门头沟学院 Java
后端岗,实习三周感觉有点想跑路了,担心秋招被拉黑,有没有佬是字节HR知道情况的
从零开始的转码生活:你实习三周都想跑路,将来拿到offer真的愿意在这干十几二十年吗
投递字节跳动等公司8个岗位
点赞 评论 收藏
分享
点赞 评论 收藏
分享
昨天 12:15
门头沟学院 Java
点赞 评论 收藏
分享
评论
56
6
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务