Skip to content

Commit 3e1cb70

Browse files
alexpantyukhinpre-commit-ci[bot]CaedenPHcclauss
authored
add algorithm to check binary search tree (TheAlgorithms#7947)
* add algorithm to check binary search tree * add tests * add leetcode link * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix typehints * typehints fixes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris <[email protected]> * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris <[email protected]> * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris <[email protected]> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix flake8 * fix typehint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add TreeNode resolving * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris <[email protected]> * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris <[email protected]> * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris <[email protected]> * Update data_structures/binary_tree/is_bst.py Co-authored-by: Christian Clauss <[email protected]> * change func name * Update data_structures/binary_tree/is_bst.py Co-authored-by: Christian Clauss <[email protected]> * review notes fixes. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix flake8 * fix flake 8 * fix doctest * Update data_structures/binary_tree/is_bst.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris <[email protected]> Co-authored-by: Christian Clauss <[email protected]>
1 parent 978414b commit 3e1cb70

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

Diff for: data_structures/binary_tree/is_bst.py

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
"""
2+
Author : Alexander Pantyukhin
3+
Date : November 2, 2022
4+
5+
Task:
6+
Given the root of a binary tree, determine if it is a valid binary search
7+
tree (BST).
8+
9+
A valid binary search tree is defined as follows:
10+
11+
- The left subtree of a node contains only nodes with keys less than the node's key.
12+
- The right subtree of a node contains only nodes with keys greater than the node's key.
13+
- Both the left and right subtrees must also be binary search trees.
14+
15+
Implementation notes:
16+
Depth-first search approach.
17+
18+
leetcode: https://leetcode.com/problems/validate-binary-search-tree/
19+
20+
Let n is the number of nodes in tree
21+
Runtime: O(n)
22+
Space: O(1)
23+
"""
24+
25+
from __future__ import annotations
26+
27+
from dataclasses import dataclass
28+
29+
30+
@dataclass
31+
class TreeNode:
32+
data: float
33+
left: TreeNode | None = None
34+
right: TreeNode | None = None
35+
36+
37+
def is_binary_search_tree(root: TreeNode | None) -> bool:
38+
"""
39+
>>> is_binary_search_tree(TreeNode(data=2,
40+
... left=TreeNode(data=1),
41+
... right=TreeNode(data=3))
42+
... )
43+
True
44+
45+
>>> is_binary_search_tree(TreeNode(data=0,
46+
... left=TreeNode(data=-11),
47+
... right=TreeNode(data=3))
48+
... )
49+
True
50+
51+
>>> is_binary_search_tree(TreeNode(data=5,
52+
... left=TreeNode(data=1),
53+
... right=TreeNode(data=4, left=TreeNode(data=3)))
54+
... )
55+
False
56+
57+
>>> is_binary_search_tree(TreeNode(data='a',
58+
... left=TreeNode(data=1),
59+
... right=TreeNode(data=4, left=TreeNode(data=3)))
60+
... )
61+
Traceback (most recent call last):
62+
...
63+
ValueError: Each node should be type of TreeNode and data should be float.
64+
65+
>>> is_binary_search_tree(TreeNode(data=2,
66+
... left=TreeNode([]),
67+
... right=TreeNode(data=4, left=TreeNode(data=3)))
68+
... )
69+
Traceback (most recent call last):
70+
...
71+
ValueError: Each node should be type of TreeNode and data should be float.
72+
"""
73+
74+
# Validation
75+
def is_valid_tree(node: TreeNode | None) -> bool:
76+
"""
77+
>>> is_valid_tree(None)
78+
True
79+
>>> is_valid_tree('abc')
80+
False
81+
>>> is_valid_tree(TreeNode(data='not a float'))
82+
False
83+
>>> is_valid_tree(TreeNode(data=1, left=TreeNode('123')))
84+
False
85+
"""
86+
if node is None:
87+
return True
88+
89+
if not isinstance(node, TreeNode):
90+
return False
91+
92+
try:
93+
float(node.data)
94+
except (TypeError, ValueError):
95+
return False
96+
97+
return is_valid_tree(node.left) and is_valid_tree(node.right)
98+
99+
if not is_valid_tree(root):
100+
raise ValueError(
101+
"Each node should be type of TreeNode and data should be float."
102+
)
103+
104+
def is_binary_search_tree_recursive_check(
105+
node: TreeNode | None, left_bound: float, right_bound: float
106+
) -> bool:
107+
"""
108+
>>> is_binary_search_tree_recursive_check(None)
109+
True
110+
>>> is_binary_search_tree_recursive_check(TreeNode(data=1), 10, 20)
111+
False
112+
"""
113+
114+
if node is None:
115+
return True
116+
117+
return (
118+
left_bound < node.data < right_bound
119+
and is_binary_search_tree_recursive_check(node.left, left_bound, node.data)
120+
and is_binary_search_tree_recursive_check(
121+
node.right, node.data, right_bound
122+
)
123+
)
124+
125+
return is_binary_search_tree_recursive_check(root, -float("inf"), float("inf"))
126+
127+
128+
if __name__ == "__main__":
129+
import doctest
130+
131+
doctest.testmod()

0 commit comments

Comments
 (0)