def build_min_height_bst_from_sorted_subarray(start, end): if start >= end: return None mid = (start + end) // 2 return BstNode(A[mid], build_min_height_bst_from_sorted_subarray(start, mid), build_min_height_bst_from_sorted_subarray(mid + 1, end))
def build_min_height_bst_from_sorted_array(A: List[int]) -> Optional[BstNode]: if not A: return None return BstNode( A[len(A) // 2], left=build_min_height_bst_from_sorted_array(A[:len(A) // 2]), right=build_min_height_bst_from_sorted_array(A[len(A) // 2 + 1:]))
def build_tree(l: int, r: int) -> Optional[BstNode]: if r < l: return None m = (l + r) // 2 root: BstNode = BstNode(A[m]) root.left = build_tree(l, m - 1) root.right = build_tree(m + 1, r) return root
def build_tree(start, end): if start > end: return None root_val = preorder_sequence[start] right_index = start + 1 while right_index <= end: if preorder_sequence[right_index] > root_val: break right_index += 1 tree = BstNode(root_val) tree.left = build_tree(start + 1, right_index - 1) tree.right = build_tree(right_index, end) return tree
def build_min_height_bst_from_sorted_array(A): if len(A) == 0: return None n = len(A) return BstNode(A[n // 2], build_min_height_bst_from_sorted_array(A[:n // 2]), build_min_height_bst_from_sorted_array(A[n // 2 + 1:]))
def build_bst(start=0, end=len(A)-1): if start > end: return None m = (start + end) // 2 left = build_bst(start, m - 1) right = build_bst(m + 1, end) return BstNode(A[m], left, right)
def build_min_height_bst_from_sorted_array(A): # SOS!!! check exactly the limits of the subarrays! if not A: return None head_idx = len(A) // 2 return BstNode(A[head_idx], build_min_height_bst_from_sorted_array(A[:head_idx]), build_min_height_bst_from_sorted_array(A[head_idx + 1:]))
def make(lower_bound, upper_bound): if index[0] == len(preorder_sequence): return None root = preorder_sequence[index[0]] if not lower_bound <= root <= upper_bound: return None index[0] += 1 L = make(lower_bound, root) R = make(root, upper_bound) return BstNode(root, L, R)
def rebuild_bst_from_preorder(preorder_sequence): if not preorder_sequence: return None point = next((i for i, val in enumerate(preorder_sequence) if val > preorder_sequence[0]), len(preorder_sequence)) return BstNode(preorder_sequence[0], rebuild_bst_from_preorder(preorder_sequence[1:point]), rebuild_bst_from_preorder(preorder_sequence[point:]))
def rebuild_bst_from_preorder(preorder_sequence): if not preorder_sequence: return None transition_point = next((i for i, a in enumerate(preorder_sequence) if a > preorder_sequence[0]), len(preorder_sequence)) return BstNode( preorder_sequence[0], rebuild_bst_from_preorder(preorder_sequence[1:transition_point]), rebuild_bst_from_preorder(preorder_sequence[transition_point:]))
def build_min_height_bst_from_sorted_array(A: List[int]) -> Optional[BstNode]: if len(A) == 0: return None root_idx = len(A) // 2 root = A[root_idx] left_list = A[:root_idx] right_list = A[root_idx + 1:] left_subtree = build_min_height_bst_from_sorted_array(left_list) right_subtree = build_min_height_bst_from_sorted_array(right_list) return BstNode(root, left_subtree, right_subtree)
def helper(root_idx, lower_bound, upper_bound): if root_idx >= len(preorder_sequence): return None elif not lower_bound <= preorder_sequence[root_idx] <= upper_bound: return None root = preorder_sequence[root_idx] root_idx += 1 return BstNode( root, helper(root_idx, lower_bound, root), helper(root_idx, root, upper_bound), )
def rebuild_bst_from_preorder( preorder_sequence: List[int]) -> Optional[BstNode]: if len(preorder_sequence) == 0: return None root = BstNode(preorder_sequence[0]) searchPath = deque([root], maxlen=len(preorder_sequence)) i = 1 while i < len(preorder_sequence): if preorder_sequence[i] < preorder_sequence[i - 1]: node = BstNode(preorder_sequence[i]) searchPath[-1].left = node searchPath.append(node) else: node = searchPath.pop() while len( searchPath) and searchPath[-1].data < preorder_sequence[i]: node = searchPath.pop() right = BstNode(preorder_sequence[i]) node.right = right searchPath.append(right) i += 1 return root
def binary_tree_from_preorder_inorder(preorder, inorder): # for a preorder traversal, the first element is the root, # followed by a set of elements for the left subtree then the right # the set of left subtree elements in the preorder traversal can be determined by # using the root element to divide the inorder traversal elements into # left and right subtree elements, # the left subtree elements in the inorder traversal is the elements that # preceeds the root element in the inorder traversal if not preorder: return None root_val = preorder[0] root = BstNode(root_val) inorder_root_index = inorder.index(root_val) inorder_left_tree = inorder[:inorder_root_index] inorder_right_tree = inorder[inorder_root_index + 1:] preorder_left_tree = preorder[1:(len(inorder_left_tree) + 1)] #skip root preorder_right_tree = preorder[(len(inorder_left_tree) + 1):] root.left = binary_tree_from_preorder_inorder(preorder_left_tree, inorder_left_tree) root.right = binary_tree_from_preorder_inorder(preorder_right_tree, inorder_right_tree) return root
def rebuild_bst_from_preorder_on_value_range(lower_bound, upper_bound): if root_idx[0] == len(preorder_sequence): return None root = preorder_sequence[root_idx[0]] if not lower_bound <= root <= upper_bound: return None root_idx[0] += 1 left_subtree = rebuild_bst_from_preorder_on_value_range( lower_bound, root) right_subtree = rebuild_bst_from_preorder_on_value_range( root, upper_bound) return BstNode(root, left_subtree, right_subtree)
def rebuild_bst_from_preorder_on_value_range(lower_bound, upper_bound): if root_idx[0] == len(preorder_sequence): return None root = preorder_sequence[root_idx[0]] if not lower_bound <= root <= upper_bound: return None root_idx[0] += 1 # Note that rebuild_bst_from_preorder_on_value_range updates root_idx[0] # So the order of following two calls are critical left_subtree = rebuild_bst_from_preorder_on_value_range( lower_bound, root) right_subtree = rebuild_bst_from_preorder_on_value_range( root, upper_bound) return BstNode(root, left_subtree, right_subtree)
def reconstruct(lower_bound, upper_bound): if root_idx[0] == len(preorder_sequence): return None root = preorder_sequence[root_idx[0]] if not (lower_bound < root < upper_bound): return None root_idx[0] += 1 left_subtree = reconstruct(lower_bound, root) right_subtree = reconstruct(root, upper_bound) return BstNode(root, left_subtree, right_subtree)
def reconstruct(preorder_start, preorder_end): if preorder_start > preorder_end: return None root = preorder_sequence[preorder_start] # Find idx where val > root partition_idx = preorder_start for i in range(preorder_start + 1, preorder_end + 1): if preorder_sequence[i] < root: partition_idx = i else: break return BstNode(root, reconstruct(preorder_start + 1, partition_idx), reconstruct(partition_idx + 1, preorder_end))
def merge_two_sorted_lists(A, B): sorted_head = BstNode() tail = sorted_head AB = [A, B] while all(AB): A_or_B = 0 if AB[0].data < AB[1].data else 1 tail.right = AB[A_or_B] tail = tail.right # Resets tail to the last node. AB[A_or_B] = tail.right if AB[0]: # Appends the remaining of A. tail.right = AB[0] elif AB[1]: # Appends the remaining of B. tail.right = AB[1] return sorted_head.right
def build_bst(lower_bound=-float('inf'), upper_bound=+float('inf')): nonlocal root_idx if root_idx >= len(preorder_sequence): return None root = preorder_sequence[root_idx] if not lower_bound < root < upper_bound: return None root_idx += 1 left = build_bst(lower_bound, root) right = build_bst(root, upper_bound) return BstNode(root, left, right)
def find_k_largest_in_bst(tree: BstNode, k: int) -> List[int]: #Reverse inorder traversal (sorta) path = [] stack = [tree] while k != 0 and stack: tree = stack.pop() if tree: if tree.left: stack.append(tree.left) if not tree.right: #Current node is the right most value path.append(tree.data) k -= 1 else: #Keeping going right, but save the current node too right = tree.right tree.left, tree.right = None, None #Prune the tree stack.append(tree) stack.append(right) return path
from test_framework import generic_test from bst_node import BstNode left_left = BstNode(4) left_right = BstNode(5) left = BstNode(1, left_left, left_right) right = BstNode(3) root = BstNode(2, left, right) print('root={}, left={}, right={}'.format(root, left, right)) root_parent_l = BstNode(6, root) root_parent_l_parent_l = BstNode(7, root_parent_l) result = [] def tree_traversal(tree, result, order): # TODO - you fill in here. if tree: if order == -1: print('Preorder: {}'.format(tree.data)) result.append(tree.data) tree_traversal(tree.left, result, order) if order == 0: print('Inorder: {}'.format(tree.data)) result.append(tree.data) tree_traversal(tree.right, result, order) if order == 1: print('Postorder: {}'.format(tree.data)) result.append(tree.data) print('tree={}, result={}'.format(tree, result)) return result
from test_framework import generic_test from bst_node import BstNode # preorder = [1,2,3], inorder=[2,1,3], ["1", "2", "3"] # preorder = [1, 2, 3, 4] inorder = [4, 3, 2, 1] ["1", "2", "null", "3", "null", "4"] # preorder = ['H','B','F','E','A','C','D','G','I'] # inorder = ['F','B','A','E','H','C','D','I','G'] pl = ['B', 'F', 'E', 'A'] il = ['F', 'B', 'A', 'E'] pr = ['C', 'D', 'G', 'I'] ir = ['C', 'D', 'I', 'G'] # left subtree a = BstNode('A') e = BstNode('E', a) f = BstNode('F') b = BstNode('B', f, e) # right subtree i = BstNode('I') g = BstNode('G', i) d = BstNode('D', None, g) c = BstNode('C', None, d) h = BstNode('H', b, c) def x_binary_tree_from_preorder_inorder(preorder, inorder): def reconstruct_tree(preorder, inorder): # TODO - you fill in here. # 1. root is first node in preorder traversal # 2. use root to divide inorder traversal into left and right subtrees (inorder) # 3. use (left,right) inorder traversal set to partition preorder traversal
def getRoot(A, low, high): if low > high: return None mid = low + ((high - low) // 2) return BstNode(A[mid], getRoot(A, low, mid - 1), getRoot(A, mid + 1, high))
from test_framework import generic_test from bst_node import BstNode left_left = BstNode(2) left_right = BstNode(4) left = BstNode(3, left_left, left_right) right = BstNode(6) root = BstNode(5, left, right) print('root={}, left={}, right={}'.format(root, left, right)) def tree_traversal(tree, order, result): # TODO - you fill in here. # print('tree_traversal,tree={},result={},order={}'.format(tree, result, order)) if tree: if order == -1: # print('Preorder: {}'.format(tree.data)) result.append(tree.data) tree_traversal(tree.left, order, result) if order == 0: # print('Inorder: {}'.format(tree.data)) result.append(tree.data) tree_traversal(tree.right, order, result) if order == 1: # print('Postorder: {}'.format(tree.data)) result.append(tree.data) # print('result={}'.format(result)) return result def preorder_traversal(tree):
def helper(i, j): if i < j: m = (j + i) // 2 return BstNode(A[m], helper(i, m), helper(m + 1, j))