每日一题·LeetCode2614·对角线上的质数

题目:

给你一个下标从 0 开始的二维整数数组 nums 。

返回位于 nums 至少一条 对角线 上的最大 质数 。如果任一对角线上均不存在质数,返回 0 。

注意:

  • 如果某个整数大于 1 ,且不存在除 1 和自身之外的正整数因子,则认为该整数是一个质数。
  • 如果存在整数 i ,使得 nums[i][i] = val 或者 nums[i][nums.length - i - 1]= val ,则认为整数 val 位于 nums 的一条对角线上。

在上图中,一条对角线是 [1,5,9] ,而另一条对角线是 [3,5,7] 。

示例 1:

输入:nums = [[1,2,3],[5,6,7],[9,10,11]]
输出:11
解释:数字 1、3、6、9 和 11 是所有 "位于至少一条对角线上" 的数字。由于 11 是最大的质数,故返回 11 。

示例 2:

输入:nums = [[1,2,3],[5,17,7],[9,11,10]]
输出:17
解释:数字 1、3、9、10 和 17 是所有满足"位于至少一条对角线上"的数字。由于 17 是最大的质数,故返回 17 。

提示:

  • 1 <= nums.length <= 300
  • nums.length == numsi.length
  • 1 <= nums[i][j] <= 4*106

 详解:

  • nums[i][i] = val (主对角线)或者 nums[i][nums.length - i - 1]= val (次对角线),就判断两条对角线上的数是否为质数。
  • 判断质数:
  • 排除 1 和特殊情况

    • 若 n≤1,直接返回 false(1 不是质数)。
    • 若 n=2 或 n=3,直接返回 true(2 和 3 是最小的质数)。
    • 若 n 是偶数(且 n≠2),直接返回 false(偶数除了 2 以外都不是质数)。
  • 只检查到 sqrt{n}

    • 若 n 有因数,那必然有一个因数小于等于 sqrt{n}​,所以只需检查 3到 sqrt{n} 之间的数是否能整除 n。
  • 跳过偶数,优化检查步长

    • 已经排除了 2,后续只需要检查奇数,减少一半计算量。
    • 进一步优化:只检查 6 的倍数附近的数(即形如 6k±1 的数),因为所有质数(除了 2 和 3)都形如 6k±1  。

代码:

 原代码:

class Solution {
    public int diagonalPrime(int[][] nums) {
        //返回最大的值
        int temp = 0;
        //判断是否为质数
        boolean judge = true;
        for (int i = 0; i < nums.length; i++) {
            //主对角线
            if (nums[i][i] > 1 && (nums[i][i] % 2 != 0 || nums[i][i] == 2)) {
                //判断是否为2,3简单质数
                if (nums[i][i] == 2 || nums[i][i] == 3) {
                    if (nums[i][i] > temp) {
                        temp = nums[i][i];
                    }
                    //质数总是在6K加减1(k取除了0的整数)
                } else if (nums[i][i] % 6 == 1 || nums[i][i] % 6 == 5) {
                    judge = true;
                    //从3到数的开平方
                    for (int j = 3; j <= Math.sqrt(nums[i][i]); j++) {
                        if (nums[i][i] % j == 0) {
                            judge = false;
                            break;
                        }
                    }
                    if (judge == true) {
                        if (nums[i][i] > temp) {
                            temp = nums[i][i];
                        }
                    }
                }
            }
            //避免对主对角线和次对角线的交点二次判断
            if (i != (nums.length - i - 1)) {
                //次对角线
                if (nums[i][nums.length - i - 1] > 1
                        && (nums[i][nums.length - i - 1] % 2 != 0 || nums[i][nums.length - i - 1] == 2)) {
                    if (nums[i][nums.length - i - 1] == 2 || nums[i][nums.length - i - 1] == 3) {
                        if (nums[i][nums.length - i - 1] > temp) {
                            temp = nums[i][nums.length - i - 1];
                        }
                    } else if (nums[i][nums.length - i - 1] % 6 == 1 || nums[i][nums.length - i - 1] % 6 == 5) {
                        judge = true;
                        for (int j = 3; j <= Math.sqrt(nums[i][nums.length - i - 1]); j++) {
                            if (nums[i][nums.length - i - 1] % j == 0) {
                                judge = false;
                                break;
                            }
                        }
                        if (judge == true) {
                            if (nums[i][nums.length - i - 1] > temp) {
                                temp = nums[i][nums.length - i - 1];
                            }
                        }
                    }
                }

            }

        }
        return temp;
    }

}

改进后:

(进行了模块化,并且减少算力,数值比原来判断的最大质数要小,就不需要判断是不是质数了)

class Solution {
    public int diagonalPrime(int[][] nums) {
        // 返回最大的值
        int max = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i][i] > max && isPrime(nums[i][i])) {
                max = nums[i][i];
            }
            if (nums[i][nums.length - 1 - i] > max && isPrime(nums[i][nums.length - 1 - i])) {
                max = nums[i][nums.length - 1 - i];
            }
        }
        return max;
    }

    public boolean isPrime(int n) {//判断是否为质数
        boolean judge = true;
        if (n != 2) {
            if (n % 6 == 1 || n % 6 == 5) {
                for (int j = 2; j <= Math.sqrt(n); j++) {
                    if (n % j == 0) {
                        judge = false;
                        break;
                    }
                }
            } else {
                judge = false;
            }
        }
        if(n==1){
            judge = false;
        }
        return judge;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值