题解 | #素数伴侣#

素数伴侣

https://www.nowcoder.com/practice/b9eae162e02f4f928eac37d7699b352e

匈牙利算法:两个数列进行配对,对于左列的每个数,让它和右列每个数尝试进行匹配。有如下原则:

  1. 先到先得:如果左列中的元素第一次找到匹配成功的右列元素,则配对;
  2. 能让则让:如果右列中被匹配到的元素还有其他选择,则让出。

之所以能够使用这个算法,是因为组成素数的两个数必须一奇一偶,否则他们的和就是偶数了,一定不是素数。

首先,将输入数组分为奇数数组和偶数数组。

其次,对于每一个偶数元素,维护一个它的配对数map,元素存放对应下标的偶数所配对成功的奇数下标

然后,遍历每个奇数,让偶数数列中的每一个数都尝试匹配。如果匹配成功,计数+1.

匹配的函数在判断的同时也更新map:

对每一个偶数和输入的奇数,如果相加是素数,则:

  • 判断这个偶数是否已经有配对
  • 如果没有配对,则更新map并返回true。
  • 如果已经有配对,则检查这个奇数能否和其他偶数匹配:
  • 如果可以,就更新map并返回true。
  • 如果不可以,不做任何操作。

最后返回false。

由上面的分析可以发现,对于每个奇数,我们需要一个visited数组,记录对应下表的偶数是否在这一轮查找中被访问过。

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // Write your code here
    let n = parseInt(await readline());
    let nums = (await readline()).split(" ").map((x) => parseInt(x));

    let primes = new Set([2, 3, 5, 7, 11, 13]);
    function isPrime(a) {
        if (primes.has(a)) return true;
        for (let i = 2; i < Math.floor(a / 2); i++) {
            if (a % i == 0) {
                return false;
            }
        }
        primes.add(a);
        return true;
    }

    let evens = nums.filter(x => x % 2);
    let odds = nums.filter(x => !evens.includes(x));

    let map = new Array(evens.length).fill(-1); // 存储偶数对应的伴侣下标

    function group(x, visited) {
        for (let i = 0; i < evens.length; i++) {
            if (!visited[i] && isPrime(x + evens[i])) {
                visited[i] = true;
                if (map[i] == -1 || group(map[i], visited)) {
                    map[i] = x;
                    return true;
                }
            }
        }
        return false;
    }

    let cnt = 0;
    for (let i = 0; i < odds.length; i++) {
        let visited = Array(evens.length).fill(false);
        if (group(odds[i], visited)) {
            cnt++;
        }
    }
    console.log(cnt);
})();

全部评论

相关推荐

2024-12-27 23:45
已编辑
三江学院 Java
程序员牛肉:死局。学历+无实习+项目比较简单一点。基本就代表失业了。 尤其是项目,功能点实在是太假了。而且提问点也很少。第一个项目中的使用jwt和threadlocal也可以作为亮点写出来嘛?第二个项目中的“后端使用restful风格”,“前端采用vue.JS”,“使用redis”也可以作为亮点嘛? 项目实在是太简单了,基本就是1+1=2的水平。而你目标投递的肯定也是小厂,可小厂哪里有什么培养制度,由于成本的问题,人家更希望你来能直接干活,所以你投小厂也很难投。基本就是死局,也不一定非要走后端这条路。可以再学一学后端之后走测试或者前端。 除此之外,不要相信任何付费改简历的。你这份简历没有改的必要了,先沉淀沉淀
点赞 评论 收藏
分享
秋招之BrianGriffin:你再跟他说华为工资也低(相对互联网)就可以享受私信爆炸了😋
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务