Skip to content

Commit 2067658

Browse files
authored
Create minimum-operations-to-make-a-subsequence.py
1 parent 2f39ee6 commit 2067658

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Time: O(nlogn)
2+
# Space: O(n)
3+
4+
import bisect
5+
6+
7+
class Solution(object):
8+
def minOperations(self, target, arr):
9+
"""
10+
:type target: List[int]
11+
:type arr: List[int]
12+
:rtype: int
13+
"""
14+
lookup = {x:i for i, x in enumerate(target)}
15+
lis = []
16+
for x in arr:
17+
if x not in lookup:
18+
continue
19+
i = bisect.bisect_left(lis, lookup[x])
20+
if i == len(lis):
21+
lis.append(lookup[x])
22+
else:
23+
lis[i] = lookup[x]
24+
return len(target)-len(lis)
25+
26+
27+
# Range Maximum Query
28+
class SegmentTree(object): # 0-based index
29+
def __init__(self, N,
30+
build_fn=lambda x, y: [y]*(2*x),
31+
query_fn=lambda x, y: y if x is None else max(x, y), # (lambda x, y: y if x is None else min(x, y))
32+
update_fn=lambda x, y: y,
33+
default_val=0):
34+
self.N = N
35+
self.H = (N-1).bit_length()
36+
self.query_fn = query_fn
37+
self.update_fn = update_fn
38+
self.default_val = default_val
39+
self.tree = build_fn(N, default_val)
40+
self.lazy = [None]*N
41+
42+
def __apply(self, x, val):
43+
self.tree[x] = self.update_fn(self.tree[x], val)
44+
if x < self.N:
45+
self.lazy[x] = self.update_fn(self.lazy[x], val)
46+
47+
def update(self, L, R, h): # Time: O(logN), Space: O(N)
48+
def pull(x):
49+
while x > 1:
50+
x //= 2
51+
self.tree[x] = self.query_fn(self.tree[x*2], self.tree[x*2+1])
52+
if self.lazy[x] is not None:
53+
self.tree[x] = self.update_fn(self.tree[x], self.lazy[x])
54+
55+
L += self.N
56+
R += self.N
57+
L0, R0 = L, R
58+
while L <= R:
59+
if L & 1: # is right child
60+
self.__apply(L, h)
61+
L += 1
62+
if R & 1 == 0: # is left child
63+
self.__apply(R, h)
64+
R -= 1
65+
L //= 2
66+
R //= 2
67+
pull(L0)
68+
pull(R0)
69+
70+
def query(self, L, R): # Time: O(logN), Space: O(N)
71+
def push(x):
72+
n = 2**self.H
73+
while n != 1:
74+
y = x // n
75+
if self.lazy[y] is not None:
76+
self.__apply(y*2, self.lazy[y])
77+
self.__apply(y*2 + 1, self.lazy[y])
78+
self.lazy[y] = None
79+
n //= 2
80+
81+
result = None
82+
if L > R:
83+
return result
84+
85+
L += self.N
86+
R += self.N
87+
push(L)
88+
push(R)
89+
while L <= R:
90+
if L & 1: # is right child
91+
result = self.query_fn(result, self.tree[L])
92+
L += 1
93+
if R & 1 == 0: # is left child
94+
result = self.query_fn(result, self.tree[R])
95+
R -= 1
96+
L //= 2
97+
R //= 2
98+
return result
99+
100+
def __str__(self):
101+
showList = []
102+
for i in xrange(self.N):
103+
showList.append(self.query(i, i))
104+
return ",".join(map(str, showList))
105+
106+
107+
# Time: O(nlogn)
108+
# Space: O(n)
109+
# segment tree solution
110+
class Solution2(object):
111+
def minOperations(self, target, arr):
112+
"""
113+
:type target: List[int]
114+
:type arr: List[int]
115+
:rtype: int
116+
"""
117+
lookup = {x:i for i, x in enumerate(target)}
118+
st = SegmentTree(len(lookup))
119+
for x in arr:
120+
if x not in lookup:
121+
continue
122+
st.update(lookup[x], lookup[x], st.query(0, lookup[x]-1)+1 if lookup[x] >= 1 else 1)
123+
return len(target)-(st.query(0, len(lookup)-1) if len(lookup) >= 1 else 0)

0 commit comments

Comments
 (0)