Minimize Branch Merge Conflicts
Company: Amazon
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: hard
Interview Round: Take-home Project
Quick Answer: This question evaluates understanding of combinatorial optimization, set operations, and order-dependent state management, requiring reasoning about how commit file modifications accumulate across branch merges.
Constraints
- 1 <= number of branches n <= 15 (small enough for subset/bitmask DP).
- Each branch has at least one commit; a commit modifies zero or more file paths.
- File paths are arbitrary strings; the same path may appear across different branches and commits.
- Duplicate paths within a commit or branch are treated as a single file (idempotent).
- The answer is the minimum total conflicting-commit count over all merge orders.
Examples
Input: ([[['a'], ['b']], [['b'], ['c']], [['a', 'c']]],)
Expected Output: 2
Explanation: Worked example. Order 0->1->2: branch 0 is 0 conflicts; branch 1's ['b'] conflicts (1); branch 2's ['a','c'] conflicts (1). Total 2, the minimum over all orderings.
Input: ([],)
Expected Output: 0
Explanation: No branches to merge, so zero conflicts.
Input: ([[['x'], ['y'], ['z']]],)
Expected Output: 0
Explanation: A single branch is always the first merged, which has zero conflicts regardless of its commits.
Input: ([[['a']], [['b']], [['c']]],)
Expected Output: 0
Explanation: Three branches touching disjoint files. No commit ever hits an already-modified file, so any order yields 0.
Input: ([[['a']], [['a']], [['a']]],)
Expected Output: 2
Explanation: All three branches touch 'a'. First branch 0 conflicts; each subsequent branch's single commit hits the modified 'a' (1 each). Order cannot avoid the 2 conflicts.
Input: ([[['a'], ['a']], [['a'], ['a']]],)
Expected Output: 2
Explanation: Both branches touch only 'a' but have two commits each. Whichever branch is merged second has both of its commits conflict on 'a' (a commit touching ['a','a'] still counts as touching 'a' once), giving 2.
Input: ([[['shared']], [['shared'], ['x'], ['y']], [['shared']]],)
Expected Output: 2
Explanation: Merge the wide branch first (0 conflicts), then the two single-commit 'shared' branches each conflict once: 0 + 1 + 1 = 2. Merging it last would cost 1 (its 'shared' commit) but leave the two 'shared' branches contributing 1, so 2 is the minimum either way here.
Input: ([[[]], [[]]],)
Expected Output: 0
Explanation: Two branches whose only commit modifies no files. An empty commit can never intersect the modified set, so total conflicts is 0.
Hints
- Only the SET of already-merged branches matters for future cost, not the order they were merged in — the union of their modified files is order-independent. This collapses n! orderings into 2^n subsets.
- Encode each distinct file path as a bit. Then each commit and each branch is an integer bitmask, and 'does this commit touch an already-modified file?' is a single bitwise AND that is non-zero.
- Let dp[S] = min conflicts to have merged exactly the branches in subset S. Transition: for each branch b not in S, dp[S | (1<<b)] = min(..., dp[S] + (commits of b whose mask intersects files(S))). Answer is dp[(1<<n)-1].
- Greedy (always merge the branch adding the fewest new conflicts) fails: merging a branch enlarges the modified-file set and raises FUTURE costs. The DP weighs both effects.