@@ -12,6 +12,27 @@ def __init__(self, root: Optional[BinaryTreeNode] = None):
1212 super ().__init__ (root )
1313 self .stack = DynamicSizeStack ()
1414
15+ def __len__ (self ) -> int :
16+ if not self .root :
17+ return 0
18+
19+ counter = 1
20+ stack = DynamicSizeStack ()
21+ stack .push (self .root )
22+
23+ while not stack .is_empty ():
24+ node = stack .pop ()
25+
26+ if node .left :
27+ counter += 1
28+ stack .push (node .left )
29+
30+ if node .right :
31+ counter += 1
32+ stack .push (node .right )
33+
34+ return counter
35+
1536 @staticmethod
1637 def construct_bst (items : List [T ]) -> Optional ["BinarySearchTree" ]:
1738 """
@@ -42,7 +63,7 @@ def construct_bst_helper(left: int, right: int) -> Optional[BinaryTreeNode]:
4263
4364 return BinarySearchTree (root = construct_bst_helper (0 , len (items ) - 1 ))
4465
45- def insert_node (self , data : T ):
66+ def insert_node (self , data : Optional [ T ] ):
4667 """
4768 Inserts a node in a BST given an element
4869 If there is no root, then create a new root node with the data and return it
@@ -64,7 +85,8 @@ def insert_helper(value: T, node: BinaryTreeNode) -> BinaryTreeNode:
6485 node .right = insert_helper (value , node .right )
6586 return node
6687
67- insert_helper (data , self .root )
88+ if data :
89+ insert_helper (data , self .root )
6890
6991 def delete_node (self , key : T ) -> Optional [BinaryTreeNode ]:
7092 """Deletes a node from the Binary Search Tree. If the node is found, it is deleted and the tree re-ordered to
@@ -116,6 +138,7 @@ def delete_helper(
116138 else :
117139 node .right = lift (node .right , node )
118140 return node
141+ return None
119142
120143 def lift (
121144 node : BinaryTreeNode , node_to_delete : BinaryTreeNode
@@ -660,6 +683,7 @@ def search_helper(current: Optional[BinaryTreeNode], value: T) -> bool:
660683 return search_helper (current .right , value )
661684 else :
662685 return search_helper (current .left , value )
686+ return False
663687
664688 return search_helper (self .root , data )
665689
@@ -801,23 +825,43 @@ def paths(self) -> list:
801825
802826 return [list (map (int , x .split ("->" ))) for x in res ]
803827
804- def __len__ (self ) -> int :
805- if not self .root :
806- return 0
828+ def inorder_successor (self , node : BinaryTreeNode ) -> Optional [BinaryTreeNode ]:
829+ """
830+ Returns the inorder successor of the node. If there is no node, None is returned. The inorder successor of the
831+ node is the node with the smallest value greater than node.data in the binary search tree.
807832
808- counter = 1
809- stack = DynamicSizeStack ()
810- stack .push (self .root )
833+ This assumes that the node is in the tree already.
811834
812- while not stack .is_empty ():
813- node = stack .pop ()
835+ Complexity:
814836
815- if node .left :
816- counter += 1
817- stack .push (node .left )
837+ Time Complexity: The time complexity of this solution is O(n) in the worst-case scenario where the given tree
838+ is skewed. However, for a balanced binary search tree, it will be O(logn).
818839
819- if node .right :
820- counter += 1
821- stack .push (node .right )
840+ Space Complexity: O(1) because we don't use any additional space.
822841
823- return counter
842+ Args:
843+ node (BinaryTreeNode): node to search for inorder successor
844+ Returns:
845+ Optional[BinaryTreeNode]: returns inorder successor of node if available, else None
846+ """
847+ if not self .root :
848+ return None
849+
850+ successor = None
851+ current = self .root
852+
853+ # current is the best candidate so far
854+ while current :
855+ # when current.data is greater than the node.data, we have found a valid successor, so, we save it in the
856+ # successor variable
857+ if current .data > node .data :
858+ successor = current
859+ # Move left to find a better(smaller) candidate. By moving to current.left, we are exploring values that
860+ # are smaller than current.data. Since we want the smallest possible successor, we must check the left
861+ # side of current to see if there is a node that is still greater than node.data, but close to node.data
862+ current = current .left
863+ else :
864+ # this node is too small, so we must go right to find a larger value
865+ current = current .right
866+
867+ return successor
0 commit comments