629 - K Inverse Pairs Array
Difficulty: Hard | Pattern: Dynamic Programming | Company tags: Google, Amazon
Problem Statement
For an integer array nums, an inverse pair is a pair of integers [nums[i], nums[j]] where 0 <= i < j < nums.length and nums[i] > nums[j].
Given two integers n and k, return the number of different arrays consisting of numbers from 1 to n such that there are exactly k inverse pairs. Since the answer can be huge, return it modulo 10^9 + 7.
Example 1:
Input: n = 3, k = 0
Output: 1 (only [1,2,3])
Example 2:
Input: n = 3, k = 1
Output: 2 ([1,3,2] and [2,1,3])
Approach: DP with Sliding Window — O(nk), O(k)
Key insight: When we insert n into an array of size n-1:
- Placing
nat positionn-1(rightmost) adds 0 new inverse pairs - Placing
nat positionn-2adds 1 new inverse pair - ...placing at position 0 adds
n-1inverse pairs
So dp[i][j] = sum(dp[i-1][j-t]) for t in 0..min(j, i-1) — a sliding window sum.
Algorithm Flow
def kInversePairs(n: int, k: int) -> int:
MOD = 10**9 + 7
dp = [0] * (k + 1)
dp[0] = 1
for i in range(1, n + 1):
new_dp = [0] * (k + 1)
window = 0
for j in range(k + 1):
window += dp[j]
if j >= i:
window -= dp[j - i]
new_dp[j] = window % MOD
dp = new_dp
return dp[k]
Dry Run
n=3, k=1
Start: dp=[1,0,0] (n=1: only [1], 0 inverse pairs)
n=2: window sums over dp, each element can add 0 or 1 inverse pair
- dp=[1,1,0] (one way for 0 pairs: [1,2]; one way for 1 pair: [2,1])
n=3: each element can add 0,1,2 inverse pairs
- j=0: window=dp[0]=1 → new_dp[0]=1
- j=1: window=dp[0]+dp[1]=2 → new_dp[1]=2
dp[1] = 2 ✓
Complexity
- Time: O(nk)
- Space: O(k)
Key Terms
| Term | Definition |
|---|---|
| Inverse pair | Indices i < j with nums[i] > nums[j] |
| Sliding window sum | Running sum maintained incrementally by adding/removing one element per step instead of recomputing |
| DP state compression | Reducing a 2D DP table to a 1D rolling array since dp[i] only depends on dp[i-1] |
| Prefix sum | Cumulative sum used to answer range-sum queries in O(1) |
FAQ
- Why does inserting
ncreate inverse pairs based on position? Placing the valuen(the largest so far) at positionpfrom the right creates exactly that many new inverse pairs, since every element to its right is smaller. - Can this be solved without the sliding window optimization?
Yes, with a naive O(n·k²) DP that sums
dp[i-1][j-t]for alltdirectly, but it's too slow for largek. - What if
kis larger than the maximum possible inverse pairs (n*(n-1)/2)? The answer is 0; the DP array naturally yields 0 since no arrangement reaches that many pairs. - Why take modulo
10^9 + 7inside the loop rather than at the end? Becausewindowaccumulates over many additions and could overflow or grow unboundedly; taking mod each step keeps values bounded. - How is this related to counting permutations by inversions?
It is the classic "Mahonian numbers" problem — counting permutations of
1..nby exact inversion count.
Quick Revision
- Problem: count permutations of
1..nwith exactlykinversions, mod1e9+7. - Build arrays incrementally: insert
iinto a permutation of sizei-1. - Inserting
iat positionpfrom the right addspnew inverse pairs (0 toi-1options). dp[i][j] = dp[i][j-1] + dp[i-1][j] - dp[i-1][j-i](sliding window sum recurrence).- Maintain a running
windowsum instead of summing a range each time — this is what makes it O(nk). - Use a 1D rolling array since each row only depends on the previous row.
- Apply modulo after every addition/subtraction to avoid overflow and keep values non-negative.
- Answer is
dp[n][k]after processing allninsertions.
Related Problems
- 96 - Unique Binary Search Trees — counting DP with similar recurrence structure
- 368 - Largest Divisible Subset — DP over ordered sequences
- Pattern match: counting DP problems with sliding-window recurrence (e.g. "Coin Change II")