Skip to content

Commit

Permalink
add algorithm to check binary search tree (TheAlgorithms#7947)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
4 people authored Nov 3, 2022
1 parent 978414b commit 3e1cb70
Showing 1 changed file with 131 additions and 0 deletions.
131 changes: 131 additions & 0 deletions data_structures/binary_tree/is_bst.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
"""
Author : Alexander Pantyukhin
Date : November 2, 2022
Task:
Given the root of a binary tree, determine if it is a valid binary search
tree (BST).
A valid binary search tree is defined as follows:
- The left subtree of a node contains only nodes with keys less than the node's key.
- The right subtree of a node contains only nodes with keys greater than the node's key.
- Both the left and right subtrees must also be binary search trees.
Implementation notes:
Depth-first search approach.
leetcode: https://leetcode.com/problems/validate-binary-search-tree/
Let n is the number of nodes in tree
Runtime: O(n)
Space: O(1)
"""

from __future__ import annotations

from dataclasses import dataclass


@dataclass
class TreeNode:
data: float
left: TreeNode | None = None
right: TreeNode | None = None


def is_binary_search_tree(root: TreeNode | None) -> bool:
"""
>>> is_binary_search_tree(TreeNode(data=2,
... left=TreeNode(data=1),
... right=TreeNode(data=3))
... )
True
>>> is_binary_search_tree(TreeNode(data=0,
... left=TreeNode(data=-11),
... right=TreeNode(data=3))
... )
True
>>> is_binary_search_tree(TreeNode(data=5,
... left=TreeNode(data=1),
... right=TreeNode(data=4, left=TreeNode(data=3)))
... )
False
>>> is_binary_search_tree(TreeNode(data='a',
... left=TreeNode(data=1),
... right=TreeNode(data=4, left=TreeNode(data=3)))
... )
Traceback (most recent call last):
...
ValueError: Each node should be type of TreeNode and data should be float.
>>> is_binary_search_tree(TreeNode(data=2,
... left=TreeNode([]),
... right=TreeNode(data=4, left=TreeNode(data=3)))
... )
Traceback (most recent call last):
...
ValueError: Each node should be type of TreeNode and data should be float.
"""

# Validation
def is_valid_tree(node: TreeNode | None) -> bool:
"""
>>> is_valid_tree(None)
True
>>> is_valid_tree('abc')
False
>>> is_valid_tree(TreeNode(data='not a float'))
False
>>> is_valid_tree(TreeNode(data=1, left=TreeNode('123')))
False
"""
if node is None:
return True

if not isinstance(node, TreeNode):
return False

try:
float(node.data)
except (TypeError, ValueError):
return False

return is_valid_tree(node.left) and is_valid_tree(node.right)

if not is_valid_tree(root):
raise ValueError(
"Each node should be type of TreeNode and data should be float."
)

def is_binary_search_tree_recursive_check(
node: TreeNode | None, left_bound: float, right_bound: float
) -> bool:
"""
>>> is_binary_search_tree_recursive_check(None)
True
>>> is_binary_search_tree_recursive_check(TreeNode(data=1), 10, 20)
False
"""

if node is None:
return True

return (
left_bound < node.data < right_bound
and is_binary_search_tree_recursive_check(node.left, left_bound, node.data)
and is_binary_search_tree_recursive_check(
node.right, node.data, right_bound
)
)

return is_binary_search_tree_recursive_check(root, -float("inf"), float("inf"))


if __name__ == "__main__":
import doctest

doctest.testmod()

0 comments on commit 3e1cb70

Please sign in to comment.