K Inverse Pairs Array
Hard · 1-D Dynamic Programming · Explanation and code example
Dynamic Programming (Space Optimized)
How it works
Since each row only depends on the previous row, we only need to keep two 1D arrays instead of the full 2D table. We maintain a running total that acts as a prefix sum, adding new values and subtracting values that fall outside the window of size N.
Steps
- Initialize
prevarray withprev[0] = 1. - For each
Nfrom1ton:- Create a new
curarray and maintain a runningtotal. - For each
Kfrom0tok:- Add
prev[K]tototal. - If
K >= N, subtractprev[K - N]fromtotal. - Set
cur[K] = total.
- Add
- Swap
prev = curfor the next iteration.
- Create a new
- Return
prev[k].
Complexity
- Time complexity:
O(n * k) - Space complexity:
O(k)
Where
nis the size of the permutation andkis the number of inverse pairs in the permutation.
Things to watch for
Forgetting Modular Arithmetic
Results can grow extremely large, requiring modulo 10^9 + 7 operations. Forgetting to apply the modulo after each addition causes integer overflow. Apply % MOD consistently in all accumulation steps.
Incorrect Handling of Negative Values in Modular Subtraction
When subtracting in the optimized recurrence (res - dp[n-1][k-n]), the result may become negative before taking modulo. Always add MOD before the final modulo: (res - value + MOD) % MOD to ensure a non-negative result.
Not Recognizing the Sliding Window Pattern
The naive approach sums n terms per cell, leading to O(n^2 * k) complexity. The key insight is that consecutive cells share most terms, allowing a sliding window optimization. Missing this pattern results in TLE on large inputs.
Off-by-One Errors in Window Boundaries
When placing element n, it can create 0 to n-1 inverse pairs (not n pairs). The window of previous row values spans k down to k - (n-1). Getting these boundaries wrong produces incorrect counts.
Missing Base Cases
The recurrence requires proper initialization: dp[0][0] = 1 (one way to arrange zero elements with zero pairs). Missing this base case or incorrectly setting dp[n][0] values propagates errors through the entire table.
Python code example
class Solution:
def kInversePairs(self, n: int, k: int) -> int:
MOD = 10**9 + 7
prev = [0] * (k + 1)
prev[0] = 1
for N in range(1, n + 1):
cur = [0] * (k + 1)
total = 0
for K in range(0, k + 1):
total = (total + prev[K]) % MOD
if K >= N:
total = (total - prev[K - N] + MOD) % MOD
cur[K] = total
prev = cur
return prev[k]
C++ code example
class Solution {
public:
int kInversePairs(int n, int k) {
const int MOD = 1e9 + 7;
vector<int> prev(k + 1, 0);
prev[0] = 1;
for (int N = 1; N <= n; N++) {
vector<int> cur(k + 1, 0);
int total = 0;
for (int K = 0; K <= k; K++) {
total = (total + prev[K]) % MOD;
if (K >= N) {
total = (total - prev[K - N] + MOD) % MOD;
}
cur[K] = total;
}
prev = cur;
}
return prev[k];
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.