-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathis_valid_bst.py
98 lines (83 loc) · 2.62 KB
/
is_valid_bst.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
#!/usr/bin/python
# Date: 2018-11-11
#
# Description:
# Check if given binary tree is valid BST or not.
#
# Approach:
# We can't just compare 3 values root.data, left.data and right.data as it may
# be possible that tree's root is 10 and somewhere down in left sub tree there
# is node having data = 5, left.data = 3 and right.data = 20 which is not
# correct as 10 is the root of this tree and no node can have value more than 10
# in left subtree.
#
# So to handle this problem, we can start scanning tree from root to leaf and
# keep track of range of values possible in child nodes. For left subtree we can
# limit max range and for right we have min range. If any node falls beyond this
# range, BST is not valid.
#
# Reference:
# https://www.youtube.com/watch?v=MILxfAbIhrE
#
# Complexity:
# O(N)
import sys
class Node:
"""Initialises a new tree node."""
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BST:
"""Manages BST."""
def __init__(self):
"""Initialises a new BST."""
self.root = None
def insert(self, root, data):
if not root:
return Node(data)
elif data < root.data:
root.left = self.insert(root.left, data)
elif data > root.data:
root.right = self.insert(root.right, data)
else:
print('Duplicate node - %d' % data)
return root
def inorder(self, root):
if root:
self.inorder(root.left)
print(root.data)
self.inorder(root.right)
def is_valid_bst(self, root, _min, _max):
"""Checks if this BST is valid."""
if not root:
return True
if root.data < _min or root.data > _max:
return False
return (self.is_valid_bst(root.left, _min, root.data) and
self.is_valid_bst(root.right, root.data, _max))
def main():
# Valid BST
valid = BST()
valid.root = valid.insert(valid.root, 10)
valid.root = valid.insert(valid.root, 5)
valid.root = valid.insert(valid.root, 20)
valid.root = valid.insert(valid.root, 4)
valid.root = valid.insert(valid.root, 7)
valid.root = valid.insert(valid.root, 15)
valid.root = valid.insert(valid.root, 25)
valid.root = valid.insert(valid.root, 30)
valid.inorder(valid.root)
print(valid.is_valid_bst(valid.root, -sys.maxint, sys.maxint)) # True
# Invalid BST
invalid = BST()
invalid.root = Node(10)
invalid.root.left = Node(5)
invalid.root.right = Node(20)
invalid.root.left.left = Node(3)
# This value is not correct, all nodes in left sub tree should be less than
# root - 10
invalid.root.left.right = Node(12)
print(valid.is_valid_bst(invalid.root, -sys.maxint, sys.maxint)) # False
if __name__ == '__main__':
main()