-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
minimum-reverse-operations.py
107 lines (97 loc) · 2.86 KB
/
minimum-reverse-operations.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
# Time: O(n * alpha(n)) = O(n)
# Space: O(n)
class UnionFind(object): # Time: O(n * alpha(n)), Space: O(n)
def __init__(self, n):
self.set = range(n)
self.rank = [0]*n
self.right = range(n) # added
def find_set(self, x):
stk = []
while self.set[x] != x: # path compression
stk.append(x)
x = self.set[x]
while stk:
self.set[stk.pop()] = x
return x
def union_set(self, x, y):
x, y = self.find_set(x), self.find_set(y)
if x == y:
return False
if self.rank[x] > self.rank[y]: # union by rank
x, y = y, x
self.set[x] = self.set[y]
if self.rank[x] == self.rank[y]:
self.rank[y] += 1
self.right[y] = max(self.right[x], self.right[y]) # added
return True
def right_set(self, x): # added
return self.right[self.find_set(x)]
# bfs, union find
class Solution(object):
def minReverseOperations(self, n, p, banned, k):
"""
:type n: int
:type p: int
:type banned: List[int]
:type k: int
:rtype: List[int]
"""
lookup = [False]*n
for i in banned:
lookup[i] = True
d = 0
result = [-1]*n
result[p] = d
uf = UnionFind(n+2)
uf.union_set(p, p+2)
q = [p]
d += 1
while q:
new_q = []
for p in q:
left, right = 2*max(p-(k-1), 0)+(k-1)-p, 2*min(p+(k-1), n-1)-(k-1)-p
p = uf.right_set(left)
while p <= right:
if not lookup[p]:
result[p] = d
new_q.append(p)
uf.union_set(p, p+2)
p = uf.right_set(p)
q = new_q
d += 1
return result
# Time: O(nlogn)
# Space: O(n)
from sortedcontainers import SortedList
# bfs, sorted list
class Solution2(object):
def minReverseOperations(self, n, p, banned, k):
"""
:type n: int
:type p: int
:type banned: List[int]
:type k: int
:rtype: List[int]
"""
lookup = [False]*n
for i in banned:
lookup[i] = True
d = 0
result = [-1]*n
result[p] = d
sl = [SortedList(i for i in xrange(0, n, 2)), SortedList(i for i in xrange(1, n, 2))]
sl[p%2].remove(p)
q = [p]
d += 1
while q:
new_q = []
for p in q:
left, right = 2*max(p-(k-1), 0)+(k-1)-p, 2*min(p+(k-1), n-1)-(k-1)-p
for p in list(sl[left%2].irange(left, right)):
if not lookup[p]:
result[p] = d
new_q.append(p)
sl[left%2].remove(p)
q = new_q
d += 1
return result