Skip to content

Commit 1781ac8

Browse files
committed
Runtime: 185 ms (Top 92.81%) | Memory: 17.30 MB (Top 67.63%)
1 parent 7228fdf commit 1781ac8

File tree

1 file changed

+19
-44
lines changed

1 file changed

+19
-44
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,21 @@
1+
// Runtime: 185 ms (Top 92.81%) | Memory: 17.30 MB (Top 67.63%)
2+
13
class Solution:
4+
# A very good description of the dp solution is at
5+
# https://leetcode.com/problems/k-inverse-pairs-array/solution/
6+
# The code below uses two 1D arrays--dp and tmp--instead if a
7+
# 2D array. tmp replaces dp after each i-iteration.
28
def kInversePairs(self, n: int, k: int) -> int:
3-
# Complexity:
4-
# - Time: O(N*K)
5-
# - Space: O(K)
6-
7-
# Special cases that can be short-circuited right away
8-
# - For k=0, there's only one solution, which is having the numbers in sorted order
9-
# DP(n, 0) = 1
10-
if k == 0:
11-
return 1
12-
# - There can't be more than n*(n-1)/2 inverse pairs, which corresponds to the numbers in reverse order
13-
# DP(n, k) = 0 for all k > n*(n-1)/2
14-
if k > n * (n - 1) // 2:
15-
return 0
16-
17-
# For the general case, we notice that:
18-
# DP(n+1, k) = sum(DP(n, i) for i in [max(0, k-n), k])
19-
# i.e., adding an additional number (the biggest one n+1):
20-
# - We can have it at the end, in which case it doesn't create any reverse pairs,
21-
# and so the number of configurations with k reverse pairs is DP(n,k)
22-
# - Or we can have it one before the end, in which case it creates exactly reverse pairs,
23-
# and so the number of configurations with k reverse pairs is DP(n,k-1)
24-
# - And so on and so forth, such that having it `i` places before the end create exactly `i` reverse pairs,
25-
# and so the number of configurations with k reverse pairs is DP(n,k-i)
26-
# This relationship allows us to compute things iteratively with a rolling window sum
27-
kLine = [0] * (k + 1)
28-
kLine[0] = 1
29-
previousKLine = kLine.copy()
30-
maxFeasibleK = 0
31-
for m in range(2, n + 1):
32-
previousKLine, kLine = kLine, previousKLine
33-
rollingWindowSum = 1
34-
maxFeasibleK += m - 1
35-
endKLineIdx = min(k, maxFeasibleK) + 1
36-
intermediateKLineIdx = min(endKLineIdx, m)
37-
for kLineIdx in range(1, intermediateKLineIdx):
38-
rollingWindowSum = (rollingWindowSum + previousKLine[kLineIdx]) % _MODULO
39-
kLine[kLineIdx] = rollingWindowSum
40-
for kLineIdx in range(intermediateKLineIdx, endKLineIdx):
41-
rollingWindowSum = (rollingWindowSum + previousKLine[kLineIdx] - previousKLine[kLineIdx - m]) % _MODULO
42-
kLine[kLineIdx] = rollingWindowSum
43-
return kLine[k]
44-
45-
46-
_MODULO = 10 ** 9 + 7
9+
dp, mod = [1]+[0] * k, 1000000007
10+
11+
for i in range(n):
12+
tmp, sm = [], 0
13+
for j in range(k + 1):
14+
sm+= dp[j]
15+
if j-i >= 1: sm-= dp[j-i-1]
16+
sm%= mod
17+
tmp.append(sm)
18+
dp = tmp
19+
#print(dp) # <-- uncomment this line to get a sense of dp from the print output
20+
# try n = 6, k = 4; your answer should be 49.
21+
return dp[k]

0 commit comments

Comments
 (0)