[LeetCode binary tree] insertion in binary search tree (701)

1. Title

Given the root node of the binary search tree (BST) and the value to be inserted into the tree, insert the value into the binary search tree. Returns the root node of the inserted binary search tree. The input data can ensure that the value to be inserted is different from any node value in the original binary search tree.

Note that there may be many effective insertion methods, as long as the tree remains a binary search tree after insertion. You can return any valid result.

1.1 example

• Example 1 1 1 :
• Input: root = [4, 2, 7, 1, 3], val = 5
• Output: [4, 2, 7, 1, 3, 5]
• Explanation: another tree that can meet the requirements of the topic is:

• Example 2 2 2 :
• Input: root = [40, 20, 60, 10, 30, 50, 70], val = 25
• Output: [40, 20, 60, 10, 30, 50, 70, null, null, 25]

1.3 restrictions

• − 1 0 8 < = val < = 1 0 8 -10^8 <= \text{val} <= 10^8 −108<=val<=108 ；
• The number of nodes on the given tree is between 0 0 0 and 1 0 4 10^4 104;
• The new value is different from any node value in the original binary search tree;
• Each node has a unique integer value ranging from 0 0 0 to 1 0 8 10^8 108 .

2. Solution I (iterative method)

2.1 analysis

To ensure that the binary search tree is still obtained after the node insertion operation on the given binary search tree, you need to find the position to be inserted in the given binary search tree first.

Specifically, when looking for the position to be inserted, it can be fully utilized Properties of binary search tree That is, Val is compared with cursor.val of the current node during each iteration:

• If cursor.val < Val, it indicates that the position to be inserted should be in the left subtree of the node node. Further:
• If the left subtree of the cursor node is not empty, it will enter the next iteration;
• If the left subtree of the cursor node is empty, perform the insert operation and return.
• If cursor.val > Val, it indicates that the position to be inserted should be in the right subtree of the node node. Further:
• If the right subtree of the cursor node is not empty, the next iteration will be performed;
• If the right subtree of the cursor node is empty, perform the insert operation and return.

2.2 realization

from typing import Optional, List

class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right

class Solution:
def inorder(self, root: TreeNode) -> List[int]:
if root is None:
return []
if not isinstance(root, TreeNode):
raise ValueError('Argument root must be an instance of TreeNode!')
return self.inorder(root.left) + [root.val] + self.inorder(root.right)

def insert_into_bst(self, root: TreeNode, val: int) -> Optional[TreeNode]:
if not isinstance(val, int):
raise ValueError('Argument val must be an instance of int!')
if root is None:
return TreeNode(val)
if not isinstance(root, TreeNode):
raise ValueError('Argument root must be an instance of TreeNode!')
cursor = root
while cursor:
if cursor.val > val:
if cursor.left:
cursor = cursor.left
else:
cursor.left = TreeNode(val)
return root
else:
if cursor.right:
cursor = cursor.right
else:
cursor.right = TreeNode(val)
return root

def main():
node5 = TreeNode(3)
node4 = TreeNode(1)
node3 = TreeNode(7)
node2 = TreeNode(2, left=node4, right=node5)
node1 = TreeNode(4, left=node2, right=node3)
root = node1
sln = Solution()
print(sln.inorder(root))  # [1, 2, 3, 4, 7]
sln.insert_into_bst(root, 5)
print(sln.inorder(root))  # [1, 2, 3, 4, 5, 7]

if __name__ == '__main__':
main()



2.3 complexity

• Time complexity: O ( n ) O(n) O(n), where n n n is the number of nodes in the tree. In the worst case, we need to insert the value into the deepest leaf node of the tree, and the deepest leaf node is O ( n ) O(n) O(n) .
• Space complexity: O ( 1 ) O(1) O(1) . Only constant size space is used here.

3. Solution II (recursive method)

3.1 analysis

The recursive method, like the iterative method, uses the properties of binary search tree, which will not be repeated here. You can directly refer to the following code.

3.2 realization

from typing import Optional, List

class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right

class Solution:
def inorder(self, root: TreeNode) -> List[int]:
if root is None:
return []
if not isinstance(root, TreeNode):
raise ValueError('Argument root must be an instance of TreeNode!')
return self.inorder(root.left) + [root.val] + self.inorder(root.right)

def recursive_insert(self, root: TreeNode, val: int) -> Optional[TreeNode]:
if root is None:
return TreeNode(val)
if root.val > val:
if root.left:
root.left = self.recursive_insert(root.left, val)
else:
root.left = TreeNode(val)
else:
if root.right:
root.right = self.recursive_insert(root.right, val)
else:
root.right = TreeNode(val)
return root

def main():
node5 = TreeNode(3)
node4 = TreeNode(1)
node3 = TreeNode(7)
node2 = TreeNode(2, left=node4, right=node5)
node1 = TreeNode(4, left=node2, right=node3)
root = node1
sln = Solution()
print(sln.inorder(root))  # [1, 2, 3, 4, 7]
sln.recursive_insert(root, 5)
print(sln.inorder(root))  # [1, 2, 3, 4, 5, 7]

if __name__ == '__main__':
main()



3.3 complexity

• Time complexity: O ( n ) O(n) O(n), where n n n is the number of nodes in the tree. In the worst case, we need to insert the value into the deepest leaf node of the tree, and the deepest leaf node is O ( n ) O(n) O(n) .
• Space complexity: O ( n ) O(n) O(n) . When the binary search tree is chained, the recursion depth is n n n. Control is the most complex.

Posted on Sun, 21 Nov 2021 18:42:52 -0500 by birdie