3

I have n arrays, each of them contain an arbitrary amount of integers. No duplicates are possible within an array ([1,1,2] can't be one of the n arrays).

I also have an integer array of size m which is filled with integers from 1 to m (value_of_an_array_entry = array_index+1). Example: m = 4, the appropriate array is [1,2,3,4].

My question:

For given n and m, is it possible to find every element in the m array by picking at most 1 element out of each of the n arrays?

An Example:

n = 3, m = 3,

The n arrays: [1], [1, 2], [2, 3]

Output should be: Yes

(because we can find every element in the m array by picking at most 1 element out of each of the n arrays. Look at the n arrays and pick 1 from the first array, 2 from the second and 3 from the third array.)

This is an interview question, I received a hint to think about the Max flow problem (I don't see how this helps me).

PlsWork
  • 1,958
  • 1
  • 19
  • 31
  • Can `n = [5,7] [8,9] [10,15] ... m = [1,2,3,4]` happen? Or is there a condition that does not allow the n and m arrays to be this different? IIRC the max flow algorithm has to do with graphs, so the n-array might be a node. You pick only 1 edge from there to get to your destination. – hamena314 Jun 02 '17 at 13:08
  • So what about the coding aspect of the problem? Maybe you wrote some code that helps you out of it?? – ShayHaned Jun 02 '17 at 13:10
  • @hamena314 such `n` arrays are possible. – PlsWork Jun 02 '17 at 13:13
  • 1
    @ShayHaned It's difficult to write code when I can't even come up with a general solution for the problem on paper. – PlsWork Jun 02 '17 at 13:14

2 Answers2

8

You can build a graph like this: The graph is divided into the left part and the right part. The left part contains n vertices which represent the n arrays. The right part contains m vertices which represent the m numbers.

enter image description here

Then we consider these n arrays. If element k is contained in the i-th array, we draw an edge between the i-th vertex from the left and the k-th vertex from the right. Our goal is to choose m edges, so that each of the m vertices on the right is covered by the m edges exactly once, and the vertices on the left is covered at most once. This is a bipartite graph maximum matching problem, which can be solved by many algorithms, including max flow.

slim
  • 40,215
  • 13
  • 94
  • 127
TsReaper
  • 845
  • 7
  • 19
1

I think a recursive method should do it.

  • If m is an empty list, PASS
  • Otherwise, look for members of m containing the first element of m
    • if none found: FAIL
    • for each one found:
      • this member of m is part of a PASS if there is a PASS for m' = tail(m) and n' = other members of (n)

I haven't tested this, but:

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;

}

Assumed methods:

  • head() returns the first element of the passed list.
  • tail() returns the passed list with the first element removed.
  • nMinus() returns a view or copy of n with nMember removed. It should not modify n.

You should use immutable collections, or at least treat them as immutable. Guava provides classes that would probably be useful. But you could quite trivially knock up a ListOmitting list wrapper class with which to implement nMinus() without Guava.

I can't say for sure it's not too brute-forcey, but it "feels" adequately efficient for an interview answer to me.

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
slim
  • 40,215
  • 13
  • 94
  • 127