Count the Number of Inversions - Video Solutions
3193. Count the Number of Inversions | DP Time Complexity | Two Pointer | DP Space Optimized
Count the Number of Inversions - Video Solution
Watch 5 video solutions for Count the Number of Inversions, a hard level problem involving Array, Dynamic Programming. This walkthrough by Aryan Mittal has 6,967 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Problem Statement
You are given an integer n and a 2D array requirements, where requirements[i] = [endi, cnti] represents the end index and the inversion count of each requirement.
A pair of indices (i, j) from an integer array nums is called an inversion if:
i < jandnums[i] > nums[j]
Return the number of permutations perm of [0, 1, 2, ..., n - 1] such that for all requirements[i], perm[0..endi] has exactly cnti inversions.
Since the answer may be very large, return it modulo 109 + 7.
Example 1:
Input: n = 3, requirements = [[2,2],[0,0]]
Output: 2
Explanation:
The two permutations are:
[2, 0, 1]- Prefix
[2, 0, 1]has inversions(0, 1)and(0, 2). - Prefix
[2]has 0 inversions.
- Prefix
[1, 2, 0]- Prefix
[1, 2, 0]has inversions(0, 2)and(1, 2). - Prefix
[1]has 0 inversions.
- Prefix
Example 2:
Input: n = 3, requirements = [[2,2],[1,1],[0,0]]
Output: 1
Explanation:
The only satisfying permutation is [2, 0, 1]:
- Prefix
[2, 0, 1]has inversions(0, 1)and(0, 2). - Prefix
[2, 0]has an inversion(0, 1). - Prefix
[2]has 0 inversions.
Example 3:
Input: n = 2, requirements = [[0,0],[1,0]]
Output: 1
Explanation:
The only satisfying permutation is [0, 1]:
- Prefix
[0]has 0 inversions. - Prefix
[0, 1]has an inversion(0, 1).
Constraints:
2 <= n <= 3001 <= requirements.length <= nrequirements[i] = [endi, cnti]0 <= endi <= n - 10 <= cnti <= 400- The input is generated such that there is at least one
isuch thatendi == n - 1. - The input is generated such that all
endiare unique.
Approach Overview
Problem Overview: You are given constraints about inversion counts in permutations. An inversion is a pair (i, j) where i < j and nums[i] > nums[j]. The task is to count how many valid permutations satisfy the required inversion conditions.
Approach 1: Brute Force Permutation Enumeration (O(n! * n), O(n))
Generate every permutation of the numbers 1..n. For each permutation, iterate through all index pairs and count inversions. After computing the inversion count, verify whether it satisfies the required condition. This approach is straightforward but infeasible beyond very small n because generating permutations costs O(n!) time. It mainly helps build intuition about how inversion counts behave in permutations.
Approach 2: Dynamic Programming on Permutation Size (O(n * k), O(n * k))
The key insight: when inserting the next largest number into a permutation, you control how many new inversions it creates. Define dp[i][j] as the number of permutations of length i that contain exactly j inversions. When placing the element i, it can be inserted in any of the i positions. Inserting it near the front adds more inversions, while inserting near the end adds fewer. The transition becomes dp[i][j] = sum(dp[i-1][j-x]) for all valid x positions where 0 ≤ x < i. This builds permutations incrementally while tracking inversion counts.
To make this efficient, compute transitions using prefix sums so each state can be calculated in constant time instead of iterating through all insertion positions. This reduces the complexity from O(n * k * n) to O(n * k). The DP table effectively enumerates all possible ways to distribute inversions across permutation sizes.
The constraints in the problem restrict which inversion counts are allowed for specific prefixes. While filling the DP table, you simply zero out states that violate those constraints. This filtering ensures that only permutations meeting all requirements remain counted.
This solution combines classic permutation inversion DP with constraint filtering. The reasoning heavily relies on understanding how inversions change when inserting elements into a sequence. Problems involving permutation structure and inversion counts often fall under Dynamic Programming combined with careful reasoning on Array positions and prefix properties.
Recommended for interviews: The dynamic programming approach with prefix-sum optimization is the expected solution. Brute force permutation generation demonstrates understanding of inversion definitions, but the DP formulation shows algorithmic maturity and the ability to optimize combinatorial counting problems.
Complexity Analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force Permutations | O(n! * n) | O(n) | Small n or for understanding inversion counting logic |
| Dynamic Programming (Basic Transition) | O(n * k * n) | O(n * k) | When implementing the straightforward DP relation for inversion insertion |
| Dynamic Programming with Prefix Sum Optimization | O(n * k) | O(n * k) | Optimal solution for large constraints and typical interview expectations |