Skip to content

Commit 7faa8dd

Browse files
authored
Create maximum-xor-of-two-non-overlapping-subtrees.py
1 parent 3712879 commit 7faa8dd

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Time: O(nlogr), r is sum(values)
2+
# Space: O(n)
3+
4+
# iterative dfs, trie
5+
class Trie(object):
6+
def __init__(self, bit_length):
7+
self.__root = {}
8+
self.__bit_length = bit_length
9+
10+
def insert(self, num):
11+
node = self.__root
12+
for i in reversed(xrange(self.__bit_length)):
13+
curr = (num>>i) & 1
14+
if curr not in node:
15+
node[curr] = {}
16+
node = node[curr]
17+
18+
def query(self, num):
19+
if not self.__root:
20+
return -1
21+
node, result = self.__root, 0
22+
for i in reversed(xrange(self.__bit_length)):
23+
curr = (num>>i) & 1
24+
if 1^curr in node:
25+
node = node[1^curr]
26+
result |= 1<<i
27+
else:
28+
node = node[curr]
29+
return result
30+
31+
32+
class Solution(object):
33+
def maxXor(self, n, edges, values):
34+
"""
35+
:type n: int
36+
:type edges: List[List[int]]
37+
:type values: List[int]
38+
:rtype: int
39+
"""
40+
def iter_dfs():
41+
lookup = [0]*len(values)
42+
stk = [(1, 0, -1)]
43+
while stk:
44+
step, u, p = stk.pop()
45+
if step == 1:
46+
stk.append((2, u, p))
47+
for v in adj[u]:
48+
if v == p:
49+
continue
50+
stk.append((1, v, u))
51+
elif step == 2:
52+
lookup[u] = values[u]+sum(lookup[v] for v in adj[u] if v != p)
53+
return lookup
54+
55+
def iter_dfs2():
56+
trie = Trie(lookup[0].bit_length())
57+
result = [0]
58+
stk = [(1, (0, -1, result))]
59+
while stk:
60+
step, args = stk.pop()
61+
if step == 1:
62+
u, p, ret = args
63+
ret[0] = max(trie.query(lookup[u]), 0)
64+
stk.append((3, (u,)))
65+
for v in adj[u]:
66+
if v == p:
67+
continue
68+
new_ret = [0]
69+
stk.append((2, (new_ret, ret)))
70+
stk.append((1, (v, u, new_ret)))
71+
elif step == 2:
72+
new_ret, ret = args
73+
ret[0] = max(ret[0], new_ret[0])
74+
elif step == 3:
75+
u = args[0]
76+
trie.insert(lookup[u])
77+
return result[0]
78+
79+
adj = [[] for _ in xrange(len(values))]
80+
for u, v in edges:
81+
adj[u].append(v)
82+
adj[v].append(u)
83+
lookup = iter_dfs()
84+
return iter_dfs2()
85+
86+
87+
# Time: O(nlogr), r is sum(values)
88+
# Space: O(n)
89+
# dfs, trie
90+
class Trie(object):
91+
def __init__(self, bit_length):
92+
self.__root = {}
93+
self.__bit_length = bit_length
94+
95+
def insert(self, num):
96+
node = self.__root
97+
for i in reversed(xrange(self.__bit_length)):
98+
curr = (num>>i) & 1
99+
if curr not in node:
100+
node[curr] = {}
101+
node = node[curr]
102+
103+
def query(self, num):
104+
if not self.__root:
105+
return -1
106+
node, result = self.__root, 0
107+
for i in reversed(xrange(self.__bit_length)):
108+
curr = (num>>i) & 1
109+
if 1^curr in node:
110+
node = node[1^curr]
111+
result |= 1<<i
112+
else:
113+
node = node[curr]
114+
return result
115+
116+
117+
class Solution2(object):
118+
def maxXor(self, n, edges, values):
119+
"""
120+
:type n: int
121+
:type edges: List[List[int]]
122+
:type values: List[int]
123+
:rtype: int
124+
"""
125+
def dfs(u, p):
126+
lookup[u] = values[u]+sum(dfs(v, u) for v in adj[u] if v != p)
127+
return lookup[u]
128+
129+
def dfs2(u, p):
130+
result = max(trie.query(lookup[u]), 0)
131+
for v in adj[u]:
132+
if v == p:
133+
continue
134+
result = max(result, dfs2(v, u))
135+
trie.insert(lookup[u])
136+
return result
137+
138+
adj = [[] for _ in xrange(len(values))]
139+
for u, v in edges:
140+
adj[u].append(v)
141+
adj[v].append(u)
142+
lookup = [0]*len(values)
143+
dfs(0, -1)
144+
trie = Trie(lookup[0].bit_length())
145+
return dfs2(0, -1)

0 commit comments

Comments
 (0)