-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathcount-the-number-of-inversions.py
136 lines (127 loc) · 4.45 KB
/
count-the-number-of-inversions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# Time: O(n * k), k = max(cnt for _, cnt in requirements)
# Space: O(n + k)
# knapsack dp, combinatorics, sliding window, two pointers
class Solution(object):
def numberOfPermutations(self, n, requirements):
"""
:type n: int
:type requirements: List[List[int]]
:rtype: int
"""
MOD = 10**9+7
lookup = [-1]*n
for i, c in requirements:
lookup[i] = c
dp = [1]
prev = 0
for i in xrange(n):
if lookup[i] != -1: # optimized
dp = [reduce(lambda total, i: (total+dp[i])%MOD, xrange(max((lookup[i]-i)-prev, 0), min((lookup[i]+1)-prev, len(dp))), 0)]
prev = lookup[i]
continue
new_dp = [0]*min(len(dp)+((i+1)-1), (lookup[-1]+1)-prev)
for j in xrange(len(new_dp)):
new_dp[j] = dp[j] if j < len(dp) else 0
if j-1 >= 0:
new_dp[j] = (new_dp[j]+new_dp[j-1])%MOD
if j-(i+1) >= 0:
new_dp[j] = (new_dp[j]-dp[j-(i+1)])%MOD
dp = new_dp
return dp[-1]
# Time: O(n * k), k = max(cnt for _, cnt in requirements)
# Space: O(n + k)
# knapsack dp, combinatorics, sliding window, two pointers
class Solution2(object):
def numberOfPermutations(self, n, requirements):
"""
:type n: int
:type requirements: List[List[int]]
:rtype: int
"""
MOD = 10**9+7
lookup = [-1]*n
for i, c in requirements:
lookup[i] = c
dp = [0]*(lookup[-1]+1)
dp[0] = 1
for i in xrange(n):
new_dp = [0]*len(dp)
if lookup[i] != -1: # optimized
new_dp[lookup[i]] = reduce(lambda total, i: (total+dp[i])%MOD, xrange(max(lookup[i]-i, 0), lookup[i]+1), 0)
else:
for j in xrange(len(dp)):
new_dp[j] = dp[j]
if j-1 >= 0:
new_dp[j] = (new_dp[j]+new_dp[j-1])%MOD
if j-(i+1) >= 0:
new_dp[j] = (new_dp[j]-dp[j-(i+1)])%MOD
dp = new_dp
return dp[-1]
# Time: O(n * k), k = max(cnt for _, cnt in requirements)
# Space: O(n + k)
# knapsack dp, combinatorics, sliding window, two pointers
class Solution3(object):
def numberOfPermutations(self, n, requirements):
"""
:type n: int
:type requirements: List[List[int]]
:rtype: int
"""
MOD = 10**9+7
lookup = [-1]*n
for i, c in requirements:
lookup[i] = c
dp = [0]*(lookup[-1]+1)
dp[0] = 1
for i in xrange(n):
new_dp = [0]*len(dp)
curr = 0
for j in xrange(len(dp)):
curr = (curr+dp[j])%MOD
if j-(i+1) >= 0:
curr = (curr-dp[j-(i+1)])%MOD
new_dp[j] = curr if lookup[i] == -1 or lookup[i] == j else 0
dp = new_dp
return dp[-1]
# Time: O(n^2 * k), k = max(cnt for _, cnt in requirements)
# Space: O(n + k)
# knapsack dp, combinatorics
class Solution4(object):
def numberOfPermutations(self, n, requirements):
"""
:type n: int
:type requirements: List[List[int]]
:rtype: int
"""
MOD = 10**9+7
lookup = [-1]*n
for i, c in requirements:
lookup[i] = c
dp = [0]*(lookup[-1]+1)
dp[0] = 1
for i in xrange(n):
dp = [reduce(lambda total, k: (total+dp[j-k])%MOD, xrange(min(i+1, j+1)), 0) if lookup[i] == -1 or lookup[i] == j else 0 for j in xrange(len(dp))]
return dp[-1]%MOD
class Solution_ConstructPermutation(object):
def numberOfPermutations(self, n, requirements):
"""
:type n: int
:type requirements: List[List[int]]
:rtype: int
"""
MOD = 10**9+7
lookup = [-1]*n
for i, c in requirements:
lookup[i] = c
dp = [[] for _ in xrange(lookup[-1]+1)]
dp[0].append([])
for i in xrange(n):
dp = [[[x+int(x >= i-k) for x in p]+[i-k] for k in xrange(min(i+1, j+1)) for p in dp[j-k]] if lookup[i] == -1 or lookup[i] == j else [] for j in xrange(len(dp))]
for p in dp[-1]:
curr = 0
for i in xrange(n):
for j in xrange(i):
curr += int(p[j] > p[i])
if lookup[i] != -1:
assert(lookup[i] == curr)
return len(dp[-1])%MOD