Match people to questions using tags and priorities
Company: Google
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates competencies in bipartite matching and combinatorial optimization, along with practical data-structure design for scalable tag-based assignment and priority-aware selection.
Part 1: Optimal person-to-question assignment
Constraints
- 0 <= len(people), len(question_tags) <= 60
- 0 <= priorities[j] <= 10^6
- Each tag is a non-empty string
- Duplicate tags may appear in an input list but should be treated as one tag
Examples
Input: ([['python', 'sql'], ['java'], ['ml']], [['sql'], ['java', 'python'], ['ml'], ['go']], [5, 7, 4, 10])
Expected Output: (3, 16)
Explanation: All three people can be matched: person 0 to question 0 or 1, person 1 to question 1, and person 2 to question 2. The best priority total among size-3 matchings is 16.
Input: ([['a'], ['a']], [['a'], ['a'], ['b']], [1, 10, 100])
Expected Output: (2, 11)
Explanation: Question 2 is impossible to answer. The maximum matching size is 2, and the best two compatible questions have priorities 10 and 1.
Input: ([['x'], ['y']], [['a'], ['b']], [5, 9])
Expected Output: (0, 0)
Explanation: No person shares any tag with any question.
Input: ([['a', 'b']], [['a'], ['b']], [2, 8])
Expected Output: (1, 8)
Explanation: Only one question can be answered because there is only one person, so choose the higher-priority compatible question.
Input: ([], [['a']], [1])
Expected Output: (0, 0)
Explanation: With no people, no question can be answered.
Hints
- Model the problem as bipartite matching: people on one side and questions on the other.
- A min-cost max-flow formulation can maximize matching size first and priority sum second by placing the priority on the question side as an edge cost.
Part 2: Brute-force matching for tiny inputs
Constraints
- 0 <= len(people), len(question_tags) <= 8
- 0 <= priorities[j] <= 10^6
- Tag lists may contain duplicates; treat them as sets
Examples
Input: ([['python'], ['sql']], [['python'], ['sql'], ['java']], [5, 3, 9])
Expected Output: (2, 8)
Explanation: The first two questions can both be answered, for a total priority of 8.
Input: ([['a'], ['a']], [['a'], ['a'], ['a']], [2, 9, 5])
Expected Output: (2, 14)
Explanation: At most two questions can be answered because there are only two people. Choose the two highest-priority compatible questions.
Input: ([['x']], [['a'], ['b']], [4, 6])
Expected Output: (0, 0)
Explanation: The single person is incompatible with every question.
Input: ([['a']], [], [])
Expected Output: (0, 0)
Explanation: There are no questions to assign.
Hints
- Process people one by one. For each person, either skip them or assign one currently unused compatible question.
- Because the limits are tiny, a recursive search over assignments is acceptable.
Part 3: Build the compatibility graph with a hash-based tag index
Constraints
- 0 <= len(people), len(question_tags) <= 10^5
- The total number of tag occurrences across all people and questions is at most 2 * 10^5
- Tag lists may contain duplicates; treat them as sets
Examples
Input: ([['python', 'sql'], ['java'], ['sql', 'ml']], [['sql'], ['java', 'python'], ['go'], []])
Expected Output: [[0, 2], [0, 1], [], []]
Explanation: Question 0 matches people 0 and 2; question 1 matches people 0 and 1; the others match nobody.
Input: ([['a', 'a'], ['b', 'a']], [['a', 'a'], ['b'], ['c']])
Expected Output: [[0, 1], [1], []]
Explanation: Duplicate tags should not create duplicate person indices.
Input: ([], [['x'], []])
Expected Output: [[], []]
Explanation: With no people, every question has an empty compatibility list.
Input: ([['x']], [[]])
Expected Output: [[]]
Explanation: A question with no tags is incompatible with everyone.
Hints
- Build a dictionary from each tag to the people who have it.
- A person may be reached through multiple tags of the same question, so remember to deduplicate.
Part 4: Online greedy assignment using priority queues
Constraints
- 0 <= len(question_tags), len(people) <= 10^5
- 0 <= priorities[j] <= 10^9
- The total number of tag occurrences across questions and people is at most 2 * 10^5
- Question tags and person tags may contain duplicates; treat them as sets
Examples
Input: ([['sql'], ['python'], ['python', 'ml']], [5, 7, 6], [['python'], ['sql', 'ml'], ['ml']])
Expected Output: [1, 2, -1]
Explanation: The first person gets question 1, the second gets question 2, and the third has no unanswered compatible question left.
Input: ([['a'], ['b'], ['a', 'b']], [4, 4, 4], [['a', 'b'], ['b'], ['a']])
Expected Output: [0, 1, 2]
Explanation: All priorities tie, so the smallest compatible question index is chosen each time.
Input: ([['a', 'a'], ['b']], [10, 3], [['a', 'a'], ['c'], []])
Expected Output: [0, -1, -1]
Explanation: Duplicate tags do not change the result. Only the first person can take question 0.
Input: ([], [], [['x']])
Expected Output: [-1]
Explanation: There are no questions to assign.
Hints
- Store questions in a max-priority structure per tag, keyed by `(-priority, question_index)`.
- Because the same question may appear in multiple heaps, use lazy deletion when a question has already been answered.