【问题标题】:MaxNotPresent- Flip some cards over so as to maximize the smallest integer that's not present on any card's frontMaxNotPresent - 翻转一些卡片以最大化任何卡片正面不存在的最小整数
【发布时间】:2019-02-05 14:25:59
【问题描述】:

你正在玩一个有 N 张牌的游戏。每张卡片的两边都有一个正整数。卡片放在桌子上。游戏的分数是正面朝上牌上没有出现的最小正整数。你可以把一些牌翻过来。翻转它们后,您然后阅读面朝上的数字并重新计算分数。你能达到的最高分是多少?

写一个函数:

class Solution { 
     public int solution(int[] A, int[] B);
}

给定两个整数数组 A 和 B,长度均为 N,描述写在卡片两面的数字,分别朝上和朝下,返回可能的最大分数。

例如,给定A = [1, 2, 4, 3] 和B = [1, 3, 2, 3],您的函数应该是return 5,因为在不翻转任何卡片的情况下,从该序列中排除的最小正整数是 5。

例如,给定A = [1, 2, 3, 3] 和B = [1, 3, 4, 3] 应该return 5。

给定 A = [4, 2, 1, 6, 5] 和 B = [3, 2, 1, 7, 7],你的函数应该返回 4,因为我们可以翻转第一张牌,这样面朝上的数字是 [3, 2, 1, 6, 5] 并且不可能同时拥有两者数字 3 和 4 朝上。

给定A = [2, 3] 和B = [2, 3],你的函数应该是return 1,因为无论怎样翻牌,面朝上的数字都是[2, 3]。

为以下假设编写一个有效的算法:

N 是[1..100,000]; 范围内的整数 数组 A、B 的每个元素都是[1..100,000,000]; 范围内的整数 输入数组大小相等

请提供解决此问题的方法。

【问题讨论】:

  • 欢迎来到 Stack Overflow - 我们很乐意帮助您解决特定的编程问题,但我们不是来为您做功课或提供免费的代码编写服务。见How to Ask 和how do I ask and answer homework questions
  • 不是作业!我无法找出解决这个问题的方法。我只是在寻找一些提示或方法。这是在在线测试期间被问到的。排序不起作用有什么可以解决这个问题的另一种最佳方法?请帮忙
  • 首先,您必须弄清楚任何卡片上没有的最小数字是多少。其次,您能否创建一个排列,使得不显示小于该数字的卡片?起泡,冲洗,重复。弄清楚你将如何手工完成。然后在计算机程序中实现这些步骤。

标签: arrays algorithm sorting search maximize


【解决方案1】:

我们可以将给定的问题转化为图论领域。

  1. 将每个 (A[i], B[i]) 对视为节点 A[i] 和节点 B[i] 之间的一条边
  2. 这又会创建许多不相交的子图。
  3. 形成的子图有两种类型:
    • 内部有循环的那个:在这种情况下,可以证明该图的每个节点都可以毫无问题地存在于其中一张卡片上。
    • 没有循环的节点:在这种情况下,应将具有最高值的节点排除在外,这将允许图中的所有其他节点当前至少出现在一张卡片上向上。

由于它将是一个无向图,我们可以使用 union-find 算法来解决循环检测问题。由于我更喜欢​​ C++,这里有一个相同的伪代码:

map<int, int> parent; // default value is 0
map<int, bool> isCyclic; // default value as false
map<int, int> maxValue; // default value as 0

int find(int x) {
    if(parent[x] == x) return x;
    parent[x] = find(parent[x]);
    return parent[x];
}

void join(int x, int y) {
    int parent_x = find(x);
    int parent_y = find(y);

    if(parent_x == parent_y) {
        isCyclic[parent_x] = true;
        return;
    }

    maxValue[parent_y] = max(maxValue[parent_x], maxValue[parent_y]);
    isCyclic[parent_y] = (isCyclic[parent_x] || isCyclic[parent_y]);
    parent[parent_x] = parent_y;
}


int solve(vector<int> A, vector<int> B) {
    int n = A.size();

    for(int i = 0; i < n; i++) {
        if(parent[A[i]] == 0) parent[A[i]] = A[i];
        if(parent[B[i]] == 0) parent[B[i]] = B[i];

        join(A[i], B[i]);
    }

    set<int> maxValues;
    for(pair<int,int> keyValue : parent) {
        // store the max values of each group in a set
        int group = find(keyValue.first);
        maxValues.insert(maxValue[group]);
    }

    for(int i = 1; i <= n; i++) {
        int group = find(i);
        if(isCyclic[group]) continue;
        if(maxValues.find(i) == maxValues.end()) return i;
    }

    return n + 1;
}

解决方案的总运行时复杂度为 O(n*log(n))。

【讨论】:

  • 这对于某些测试用例不起作用,例如:A=[1,1] 和 B=[2,3] 其中预期 ans 应该是 3 但如果它以上述方式排序,那么我们将排序结构为 ((min(A[i],B[i]),A[i],B[i]))=(1,1,2),(1,1,3)...根据您的方法,列表将是 list=(1,3) 这将给出 2 而不是 3 的答案。我认为关键在于我们如何对结构进行排序
  • 啊,是的,我匆忙错过了那个案子。我现在更新了我的解决方案。希望它应该解决。如果还有问题,请告诉我。
  • 好吧...那么它不适用于 A=[1, 2, 4, 3] B= [1, 3, 2, 3]) 的情况...我们的排序结构变为 ( (min(A[i],B[i]),A[i],B[i]))=(1 1 1 ),(2 4 2 ),(2 2 3 ),(3 3 3 ) 和list 变为 list=(1,2,3) 但理想情况下答案应该是 5 。在这里查看问题app.codility.com/programmers/challenges/germanium2018
  • 我的错!我已经修改了我的方法来做一些不同的事情。让我知道这是否可以正常工作?
  • 我尝试了这种方法,它通过了很多案例......但对于 A[1,1] 和 B[3,2] 等案例失败了......而且时间复杂度更高,它给了时间大型案例的限制错误...谢谢
猜你喜欢
  • 2014-02-25
  • 1970-01-01
  • 2021-02-19
  • 2021-05-15
  • 2018-09-06
  • 2017-04-03
  • 2021-10-31
  • 1970-01-01
  • 2018-08-27
相关资源
最近更新 更多