mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-27 15:01:08 +00:00
Simplify is_bst.py (#10627)
* Simplify is_bst.py * updating DIRECTORY.md * Update is_bst.py * Rename is_bst.py to is_sorted.py * updating DIRECTORY.md * Update data_structures/binary_tree/is_sorted.py Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com> --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>
This commit is contained in:
parent
6987614067
commit
26ffad9d17
|
@ -199,7 +199,8 @@
|
||||||
* [Flatten Binarytree To Linkedlist](data_structures/binary_tree/flatten_binarytree_to_linkedlist.py)
|
* [Flatten Binarytree To Linkedlist](data_structures/binary_tree/flatten_binarytree_to_linkedlist.py)
|
||||||
* [Floor And Ceiling](data_structures/binary_tree/floor_and_ceiling.py)
|
* [Floor And Ceiling](data_structures/binary_tree/floor_and_ceiling.py)
|
||||||
* [Inorder Tree Traversal 2022](data_structures/binary_tree/inorder_tree_traversal_2022.py)
|
* [Inorder Tree Traversal 2022](data_structures/binary_tree/inorder_tree_traversal_2022.py)
|
||||||
* [Is Bst](data_structures/binary_tree/is_bst.py)
|
* [Is Sorted](data_structures/binary_tree/is_sorted.py)
|
||||||
|
* [Is Sum Tree](data_structures/binary_tree/is_sum_tree.py)
|
||||||
* [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py)
|
* [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py)
|
||||||
* [Lowest Common Ancestor](data_structures/binary_tree/lowest_common_ancestor.py)
|
* [Lowest Common Ancestor](data_structures/binary_tree/lowest_common_ancestor.py)
|
||||||
* [Maximum Fenwick Tree](data_structures/binary_tree/maximum_fenwick_tree.py)
|
* [Maximum Fenwick Tree](data_structures/binary_tree/maximum_fenwick_tree.py)
|
||||||
|
|
|
@ -1,131 +0,0 @@
|
||||||
"""
|
|
||||||
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()
|
|
97
data_structures/binary_tree/is_sorted.py
Normal file
97
data_structures/binary_tree/is_sorted.py
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
|
||||||
|
In effect, a binary tree is a valid BST if its nodes are sorted in ascending order.
|
||||||
|
leetcode: https://leetcode.com/problems/validate-binary-search-tree/
|
||||||
|
|
||||||
|
If n is the number of nodes in the tree then:
|
||||||
|
Runtime: O(n)
|
||||||
|
Space: O(1)
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Iterator
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Node:
|
||||||
|
data: float
|
||||||
|
left: Node | None = None
|
||||||
|
right: Node | None = None
|
||||||
|
|
||||||
|
def __iter__(self) -> Iterator[float]:
|
||||||
|
"""
|
||||||
|
>>> root = Node(data=2.1)
|
||||||
|
>>> list(root)
|
||||||
|
[2.1]
|
||||||
|
>>> root.left=Node(data=2.0)
|
||||||
|
>>> list(root)
|
||||||
|
[2.0, 2.1]
|
||||||
|
>>> root.right=Node(data=2.2)
|
||||||
|
>>> list(root)
|
||||||
|
[2.0, 2.1, 2.2]
|
||||||
|
"""
|
||||||
|
if self.left:
|
||||||
|
yield from self.left
|
||||||
|
yield self.data
|
||||||
|
if self.right:
|
||||||
|
yield from self.right
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_sorted(self) -> bool:
|
||||||
|
"""
|
||||||
|
>>> Node(data='abc').is_sorted
|
||||||
|
True
|
||||||
|
>>> Node(data=2,
|
||||||
|
... left=Node(data=1.999),
|
||||||
|
... right=Node(data=3)).is_sorted
|
||||||
|
True
|
||||||
|
>>> Node(data=0,
|
||||||
|
... left=Node(data=0),
|
||||||
|
... right=Node(data=0)).is_sorted
|
||||||
|
True
|
||||||
|
>>> Node(data=0,
|
||||||
|
... left=Node(data=-11),
|
||||||
|
... right=Node(data=3)).is_sorted
|
||||||
|
True
|
||||||
|
>>> Node(data=5,
|
||||||
|
... left=Node(data=1),
|
||||||
|
... right=Node(data=4, left=Node(data=3))).is_sorted
|
||||||
|
False
|
||||||
|
>>> Node(data='a',
|
||||||
|
... left=Node(data=1),
|
||||||
|
... right=Node(data=4, left=Node(data=3))).is_sorted
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
TypeError: '<' not supported between instances of 'str' and 'int'
|
||||||
|
>>> Node(data=2,
|
||||||
|
... left=Node([]),
|
||||||
|
... right=Node(data=4, left=Node(data=3))).is_sorted
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
TypeError: '<' not supported between instances of 'int' and 'list'
|
||||||
|
"""
|
||||||
|
if self.left and (self.data < self.left.data or not self.left.is_sorted):
|
||||||
|
return False
|
||||||
|
if self.right and (self.data > self.right.data or not self.right.is_sorted):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
||||||
|
tree = Node(data=2.1, left=Node(data=2.0), right=Node(data=2.2))
|
||||||
|
print(f"Tree {list(tree)} is sorted: {tree.is_sorted = }.")
|
||||||
|
assert tree.right
|
||||||
|
tree.right.data = 2.0
|
||||||
|
print(f"Tree {list(tree)} is sorted: {tree.is_sorted = }.")
|
||||||
|
tree.right.data = 2.1
|
||||||
|
print(f"Tree {list(tree)} is sorted: {tree.is_sorted = }.")
|
Loading…
Reference in New Issue
Block a user