Skip to main content

Minimize Inversions in a Prefix Tree - Solution & Explanation

Hard5 min read
Practice this problem

Problem Statement

You are given an array words of n unique strings containing only lowercase English letters from 'a' to 'j'. You are also given an integer array target containing each index from 0 to n - 1 exactly once.

Build a prefix tree from words:

  • The root represents the empty string "".
  • Each other node represents a different non-empty prefix of a word. The parent of a node is the prefix obtained by removing its last character.
  • The node representing the complete word words[i] is marked with index i. A marked node may also have children.

You may choose the order of the children of each node independently. You cannot change which node is a child's parent.

Traverse the tree starting at the root. When visiting a node, first record its index if it is marked. Then visit its children in the chosen order, completing the traversal of each child before moving to the next. This is a pre-order traversal.

The recorded indices form an array traversal of length n. Let pos[i] be the position of index i in target.

An inversion is a pair of positions (a, b) such that 0 <= a < b < n and pos[traversal[a]] > pos[traversal[b]].

Return the minimum possible number of inversions over all choices of child orderings.

 

Example 1:

​​​​​​​​​​​​​​​​​​​​​

Input: words = ["bad","bag","fig","fed"], target = [3,1,0,2]

Output: 2

Explanation:

Visit the root's "f" child before its "b" child. Within the "f" branch, visit "fed" before "fig". Within the "b" branch, visit "bag" before "bad".

This produces traversal = [3,2,1,0]:

Traversal position Word index Word Position in target
0 3 "fed" 0
1 2 "fig" 3
2 1 "bag" 1
3 0 "bad" 2

The positions in target are [0,3,1,2]. The inversions are the pairs of traversal positions (1,2) and (1,3), since 3 > 1 and 3 > 2.

No child ordering produces fewer than 2 inversions.

Example 2:

Input: words = ["ab","ac","ba","bc"], target = [0,3,1,2]

Output: 1

Explanation:

Visit the root's "a" child before its "b" child. Within these branches, visit "ab" before "ac", and "bc" before "ba".

This produces traversal = [0,1,3,2]:

Traversal position Word index Word Position in target
0 0 "ab" 0
1 1 "ac" 2
2 3 "bc" 1
3 2 "ba" 3

The positions in target are [0,2,1,3]. The only inversion is the pair of traversal positions (1,2), since 2 > 1.

No child ordering produces zero inversions.

 

Constraints:

  • 1 <= n == words.length <= 104
  • 1 <= words[i].length <= 20
  • words[i] contains only lowercase English letters from 'a' to 'j'​​​​​​​
  • All words[i] are unique
  • 0 <= target[i] <= n - 1
  • target is a permutation of integers from 0 to n - 1

Approach Overview

Problem Overview: You get a prefix tree (trie) where each node's children can be reordered. Each reordering changes the sequence of values read off the tree, and you want the arrangement that produces the fewest inversions, meaning pairs that appear out of order.

Approach 1: Brute Force Over All Child Orderings (Exponential)

Enumerate every permutation of children at every node, build the resulting sequence, and count inversions with a nested loop. The number of arrangements grows as the product of factorials of child counts, so this is only useful for checking small inputs. It runs in O(k! * n^2) time and O(n) space, where k is the largest branching factor. Use it to validate a faster solution on tiny test cases, not as a submission.

Approach 2: Recursive Greedy with Pairwise Inversion Counts (O(n^2))

Process the tree bottom-up with DFS. For each node, compute the sequence produced by each child subtree and the cross-inversions between every pair of children, in both possible orders. Then pick the order that yields fewer cross-inversions. The key insight is that choices at different nodes are independent, so a local greedy decision at each node gives a global optimum. Count cross-inversions with nested loops over the child sequences. This is simpler to reason about than the optimal version, and it is fast enough for moderate inputs. Time is O(n^2) in the worst case and space is O(n) for the recursion and stored sequences.

Approach 3: Greedy DFS with Merge-Based Inversion Counting (Optimal, O(n log n))

Keep the same bottom-up greedy idea, but replace the nested loops with a merge step from merge sort. Each subtree returns its sorted sequence along with an inversion count. When merging two child sequences, one merge pass counts how many elements from the left child exceed elements from the right child, which gives both cross-inversion totals in linear time. Swap the children only when the swapped order gives fewer cross-inversions, then merge. Total time is O(n log n) and space is O(n). Prefer this approach whenever the input is large, because the nested-loop version hits its limit quickly.

Recommended for interviews: Interviewers expect you to state the brute force, then justify the greedy per-node choice, and finally implement the merge-based counting. The brute force shows you understand the search space. The greedy argument and the merge-based count show you can cut it down to O(n log n). Explain why independent subtree choices compose correctly before you write any code.

Related topics: tree, divide and conquer, sorting.

Solutions for this problem are being prepared.

Try solving it yourself

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Brute Force (all orderings)O(k! * n^2)O(n)Validating answers on tiny inputs
Greedy with nested loop countsO(n^2)Moderate inputs, easier to reason about
Greedy DFS with merge countingO(n log n)General case, large inputs, interview answer

Video Solution

4075. Minimize Inversions in a Prefix Tree (Leetcode Hard)

Frequently Asked Questions

Is Minimize Inversions in a Prefix Tree easy or hard?
It is rated Hard, with a 33.4% acceptance rate. The difficulty comes from proving that local per-node greedy choices give a global optimum and from implementing the merge-based counting correctly.
How to solve Minimize Inversions in a Prefix Tree in O(n log n)?
Process the tree with DFS and return a sorted sequence plus an inversion count from each subtree. At each node, count cross-inversions between children during a merge step, swap children if the swapped order has fewer inversions, then merge. The per-node choices are independent, so the greedy result is globally optimal.
What is the best approach for Minimize Inversions in a Prefix Tree?
The best approach is a bottom-up greedy DFS that uses merge-based inversion counting. At each node, you compare the cross-inversions for both child orders and keep the cheaper one, merging sorted child sequences in the same pass. This runs in O(n log n) time with O(n) space.
What data structure is used in Minimize Inversions in a Prefix Tree?
The problem uses a tree, specifically a prefix tree, as the input structure. The solution relies on recursion or an explicit stack for DFS, and on arrays or lists to hold sorted child sequences during the merge step.
What is the time complexity of Minimize Inversions in a Prefix Tree?
The optimal solution runs in O(n log n) time, where n is the number of nodes. The naive version that counts cross-inversions with nested loops takes O(n^2), and enumerating all child orderings takes factorial time.
Minimize Inversions in a Prefix Tree Python solution: how do I write it?
In Python, write a recursive DFS that returns a (sorted list, inversion count) pair for each node. Merge the children's lists with a two-pointer pass that counts cross-inversions, and choose the child order that gives the smaller count. Use an iterative stack if recursion depth could exceed Python's default limit.
Is Minimize Inversions in a Prefix Tree asked at Google, Amazon, or Meta?
This problem is tagged as General on FleetCode, so company-specific frequency is not listed. Problems that combine tree traversal with merge sort style counting appear often in senior-level interviews at large tech companies, so practice the merge-based version.

Ready to solve this problem?

Practice Minimize Inversions in a Prefix Tree with our built-in code editor and test cases.

Practice on FleetCode