通过从n个数组中的每个数组中选取最多1个元素来查找n个数组中的m个元素

时间:2017-06-02 12:57:14

标签: java arrays algorithm max-flow

我有n个数组,每个数组都包含任意数量的整数。数组中不可能有重复项([1,1,2]不能成为n数组之一。)

我还有一个大小为m的整数数组,其中填充了从1m的整数(value_of_an_array_entry = array_index + 1)。示例:m = 4,相应的数组为[1,2,3,4]

我的问题:

对于给定的nm,是否可以通过从每个m数组中挑选最多1个元素来查找n数组中的每个元素?

一个例子:

n = 3, m = 3,

n数组:[1][1, 2][2, 3]

输出应为:Yes

(因为我们可以通过从每个m数组中挑选最多1个元素来查找n数组中的每个元素。查看n数组并选择{{1来自第一个数组,来自第二个数组的1和来自第三个数组的2。)

这是一个面试问题,我收到了一个关于Max流量问题的提示(我不知道这对我有什么帮助)。

2 个答案:

答案 0 :(得分:8)

您可以构建如下图形:图形分为左侧部分和右侧部分。左侧部分包含n个顶点,代表n数组。右侧部分包含m个顶点,代表m个数字。

enter image description here

然后我们考虑这些n数组。如果元素k包含在i - 数组中,我们在左边的i个顶点和右边的k个顶点之间绘制一条边。我们的目标是选择m边,以便右侧的每个m顶点都被m边缘恰好覆盖一次,而左边的顶点最多被覆盖一次。这是一个二分图最大匹配问题,可以通过许多算法解决,包括最大流量。

答案 1 :(得分:1)

我认为递归方法应该这样做。

  • 如果m是空列表,则为PASS
  • 否则,查找包含m的第一个元素的m的成员
    • 如果没有找到:FAIL
    • 找到的每个人:
      • 如果m' = tail(m)n' = other members of (n)
      • 有通行证,则此m成员属于通行证的一部分

我没有测试过这个,但是:

public boolean check(List<Integer> m, List<List<Integer>> n) {
    if (m.isEmpty()) {
        return true;
    }

    int head = head(m);
    List<Integer> tail = tail(m);

    for (List<Integer> nMember : n) {
        if (nMember.contains(head) && check(tail, nMinus(n, nMember))) {
            return true;
        }
    }

    return false;

}

假设方法:

  • head()返回传递列表的第一个元素。
  • tail()返回已删除第一个元素的传递列表。
  • nMinus()会返回已移除n的{​​{1}}的视图或副本。它不应该修改nMember

您应该使用不可变集合,或者至少将它们视为不可变集合。 Guava提供了可能有用的类。但是你可以非常简单地敲定一个n列表包装类,用它来实现没有Guava的ListOmitting

我不能肯定地说它不是太暴力,但它对于我的采访答案“感觉”足够有效。