|
1 |
| -class Trie: |
2 |
| - def __init__(self): |
3 |
| - self.root = {} |
4 |
| - |
5 |
| - def add(self, word): |
6 |
| - cur = self.root |
7 |
| - for c in word: |
8 |
| - if c not in cur: |
9 |
| - cur[c] = {} |
10 |
| - cur = cur[c] |
11 |
| - |
12 |
| - def find(self, word): |
13 |
| - cur = self.root |
14 |
| - res = "" |
15 |
| - for c in word: |
16 |
| - desired = "1" if c == "0" else "0" |
17 |
| - if not desired in cur: |
18 |
| - desired = c |
19 |
| - res += desired |
20 |
| - cur = cur[desired] |
21 |
| - return res |
22 |
| - |
23 |
| - def delete(self, word): |
24 |
| - cur = self.root |
25 |
| - path = [] |
26 |
| - for c in word: |
27 |
| - path.append(cur) |
28 |
| - cur = cur[c] |
29 |
| - for c, obj in zip(word[::-1], path[::-1]): |
30 |
| - if not obj[c]: |
31 |
| - del obj[c] |
32 |
| - else: |
33 |
| - break |
34 |
| - |
35 |
| - |
| 1 | +# Runtime: 6663 ms (Top 46.4%) | Memory: 339.09 MB (Top 7.1%) |
| 2 | + |
36 | 3 | class Solution:
|
37 | 4 | def maxGeneticDifference(self, parents: List[int], queries: List[List[int]]) -> List[int]:
|
38 |
| - #since max(10^5,2*10^5) < 2^18, 18 bits are enough to represent a value or node as a bit string |
39 |
| - def makebin(x): |
40 |
| - return bin(x)[2:].zfill(18) |
41 |
| - node_queries = defaultdict(list) |
42 |
| - for i, (node, val) in enumerate(queries): |
43 |
| - node_queries[node].append((i,val)) |
44 |
| - graph = defaultdict(list) |
45 |
| - for y, x in enumerate(parents): |
46 |
| - graph[x].append(y) |
47 |
| - res = [-1 for _ in queries] |
48 |
| - tree = Trie() |
49 |
| - #dfs traversal |
50 |
| - #during the traversal, it is making bit Trie using the nodes from the root to the current node of the graph |
51 |
| - def dfs(v): |
52 |
| - v_bin = makebin(v) |
53 |
| - tree.add(v_bin) |
54 |
| - for i, val in node_queries[v]: |
55 |
| - val_bin = makebin(val) |
56 |
| - target_bin = tree.find(val_bin) |
57 |
| - res[i] = int(target_bin,2)^val |
58 |
| - for w in graph[v]: |
59 |
| - dfs(w) |
60 |
| - tree.delete(v_bin) |
61 |
| - dfs(graph[-1][0]) #dfs from the root |
| 5 | + adj_map = collections.defaultdict(set) |
| 6 | + root = None |
| 7 | + for i, node in enumerate(parents): |
| 8 | + if node == -1: |
| 9 | + root = i |
| 10 | + else: |
| 11 | + adj_map[node].add(i) |
| 12 | + queries_map = collections.defaultdict(set) |
| 13 | + |
| 14 | + for q in queries: |
| 15 | + queries_map[q[0]].add(q[1]) |
| 16 | + self.res_map = {} |
| 17 | + def helperDFS(curr_root,prefix_map): |
| 18 | + |
| 19 | + if curr_root in queries_map: |
| 20 | + for val in queries_map[curr_root]: |
| 21 | + bin_rep = format(val, '020b') |
| 22 | + best_bin = "" |
| 23 | + print(bin_rep) |
| 24 | + for i in range(20): |
| 25 | + if prefix_map[best_bin+str(1-int(bin_rep[i]))]: |
| 26 | + best_bin += str(1-int(bin_rep[i])) |
| 27 | + else: |
| 28 | + best_bin += bin_rep[i] |
| 29 | + self.res_map[(curr_root,val)] = int(best_bin,2) ^ val |
| 30 | + for child in adj_map[curr_root]: |
| 31 | + bin_rep = format(child, '020b') |
| 32 | + for i in range(1, len(bin_rep)+1): |
| 33 | + prefix_map[bin_rep[0:i]].add(child) |
| 34 | + helperDFS(child, prefix_map) |
| 35 | + for i in range(1, len(bin_rep)+1): |
| 36 | + prefix_map[bin_rep[0:i]].remove(child) |
| 37 | + |
| 38 | + initial_prefixmap = collections.defaultdict(set) |
| 39 | + root_rep = format(root, '020b') |
| 40 | + for i in range(1,21): |
| 41 | + initial_prefixmap[root_rep[0:i]].add(root) |
| 42 | + helperDFS(root, initial_prefixmap) |
| 43 | + res = [] |
| 44 | + for q in queries: |
| 45 | + res.append(self.res_map[(q[0],q[1])]) |
62 | 46 | return res
|
63 | 47 |
|
0 commit comments