-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy path8_Google_Unival_trees.py
executable file
·127 lines (99 loc) · 3.77 KB
/
8_Google_Unival_trees.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
'''
This problem was asked by Google.
A unival tree (which stands for "universal value") is a tree where all nodes under it have the same value.
Given the root to a binary tree, count the number of unival subtrees.
For example, the following tree has 5 unival subtrees:
0
/ \
1 0
/ \
1 0
/ \
1 1
'''
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right= right
def print_node(self):
print(self.data)
def print_inorder(self):
if self.left: # left exists
self.left.print_inorder()
print(self.data)
if self.right:
self.right.print_inorder()
def insert(self, data):
if (data <= self.data): # add to the left
if self.left == None: # left empty
self.left = Node(data)
else: # left exists
self.left.insert(data)
else: # add to the right
if self.right == None: # right empty
self.right = Node(data)
else: # right exists
self.right.insert(data)
def helper(root, root_val):
if root is None:
return True
elif root.val == root_val:
return helper(root.left,root_val) and helper(root.right, root_val)
return False
def check_unival(root):
return helper(root, root.val)
def count_unival_subtrees(root):
if root is None:
return 0
left = count_unival_subtrees(root.left)
right = count_unival_subtrees(root.right)
return 1 + left + right if check_unival(root) else left + right
# -------------------------------
# Bottom up approach
def bottom_up_helper(root, val):
'''
If this is the input tree
0
/ \
1 0
/ \
1 0
/ \
1 1
than these are the calculations that happen, starting from the leaf nodes. Calculations in '()'
0
(1,F)/ \(4,F)
1 0
(3,F)/ \(1,T)
1 0
(1,T)/ \(1,T)
1 1
'''
if root is None:
return 0, True
left_count, l_nodes_match = bottom_up_helper(root.left, root.val) # go left and find if values match root
right_count, r_nodes_match = bottom_up_helper(root.right, root.val) # go right and find if vales match root
if left_count == 0 and right_count ==0 and l_nodes_match is True and r_nodes_match is True:
# got a leaf
if root.val == val: # leaf's value matches root's vale
return 1,True # return 1=> unival sub tree, & True
else: # leaf's value does not match root's value
return 1,False
else:
if (l_nodes_match and r_nodes_match) is True and root.val == val: # right and left sub trees values match root
return 1 + left_count + right_count, True
elif (l_nodes_match and r_nodes_match) is True and root.val != val:
return 1 + left_count + right_count, False
else:
return left_count + right_count, False
def count_unival_bottom_up(root):
count, _ = bottom_up_helper(root, root.val)
return count
if __name__ == '__main__':
root = Node(0, left= Node(1), right= Node(0, left=Node(1, left=Node(1), right=Node(1)), right=Node(0)))
# root = Node(1, left=Node(1), right=Node(1))
# root = Node(5, left=Node(5, left=Node(5), right=Node(5)), right=Node(5, left=None, right=Node(5))) # Ans=6
# root = Node(5, left=Node(1, left=Node(5), right=Node(5)), right=Node(5, left=None, right=Node(5))) # Ans = 4
# root = Node(5, left=Node(4, left=Node(4), right=Node(4)), right=Node(5, left=None, right=Node(5))) # Ans = 5
print(count_unival_bottom_up(root))