def insertIntoMaxTree(self, root: TreeNode, val: int) -> TreeNode: if root is None or root is not None and root.val < val: node = TreeNode(val) node.left = root return node root.right = self.insertIntoMaxTree(root.right, val) return root
def make_example_1(): root = TreeNode(1) root.left = TreeNode(2) root.right = TreeNode(2) root.left.left = TreeNode(3) root.left.right = TreeNode(4) root.right.left = TreeNode(4) root.right.right = TreeNode(3) return root
def sortedArrayToBST(self, nums: List[int]) -> TreeNode: if nums: nums_left, middle, nums_right = nums[:len(nums) // 2], nums[len(nums) // 2], nums[len(nums) // 2 + 1:] tree = TreeNode(middle) tree.left = self.sortedArrayToBST(nums_left) tree.right = self.sortedArrayToBST(nums_right) return tree
def sortedArrayToBST(self, nums: List[int]) -> TreeNode: length = len(nums) if length == 0: return None else: idx = length // 2 node = TreeNode(nums[idx]) node.left = self.sortedArrayToBST(nums[:idx]) node.right = self.sortedArrayToBST(nums[idx + 1:]) return node
def generate_tree_with_range(start, end): if start > end: return [None] result = [] for index in range(start, end + 1): for left_tree in generate_tree_with_range(start, index - 1): for right_tree in generate_tree_with_range(index + 1, end): this_node = TreeNode(index) this_node.left, this_node.right = left_tree, right_tree result.append(this_node) return result
def construct_tree(nums, left, right): if left >= right: return None max_i = left for index in range(left + 1, right): if nums[index] > nums[max_i]: max_i = index node = TreeNode(nums[max_i]) node.left = construct_tree(nums, left, max_i) node.right = construct_tree(nums, max_i + 1, right) return node
def make_example(): root = TreeNode(3) root.left = TreeNode(9) root.right = TreeNode(20) root.left.left = TreeNode(3) root.right.left = TreeNode(15) root.right.right = TreeNode(7) return root
def sortedArrayToBST(self, num): if not num: return None if len(num) % 2 == 0: mid = len(num)/2 - 1 else: mid = (len(num)+1)/2 - 1 root = TreeNode(num[mid]) root.left = self.sortedArrayToBST(num[:mid]) root.right = self.sortedArrayToBST(num[mid+1:]) return root
def sortedArrayToBST(self, nums): """ :type nums: List[int] :rtype: TreeNode """ if nums is None or len(nums) == 0: return None mid_index = len(nums) >> 1 node = TreeNode(nums[mid_index]) node.left = self.sortedArrayToBST(nums[:mid_index]) node.right = self.sortedArrayToBST(nums[mid_index + 1:]) return node
def make_example_2(): root = TreeNode(5) root.left = TreeNode(1) root.right = TreeNode(4) root.right.left = TreeNode(3) root.right.right = TreeNode(6) return root
def deserialize(self, data): """Decodes your encoded data to tree. :type data: str :rtype: TreeNode """ if data == "[]": return None values = list(map(lambda x: x.strip(), data[1:-1].split(','))) root = None q = Queue() for value in values: if value == "null": current = None else: current = TreeNode(int(value)) if q.empty(): root = current else: parent, direction = q.get() if not direction: parent.left = current else: parent.right = current if current is not None: q.put((current, 0)) q.put((current, 1)) return root
def copy_from_iterable(self, iterable): """ Copies data from iterable, which are put into the binary tree in level order Args: iterable (iterable): iterable object from which contents are copied and put into binary tree Returns: root node of the binary tree """ # initialize root node self._root = TreeNode(iterable[0], 0) iterable_size = len(iterable) # create a list of tree nodes with each saving data from iterable # but topoligical relation has not been established yet # note that nodes saved in iterable are mapped to binary tree node in level order node_queue = [self._root] for i, data in enumerate(iterable[1:]): inserting_right = i & 1 node_queue.append( TreeNode(data, -1 if inserting_right else 1) if data else None) i = 1 while i < iterable_size: current_node = node_queue[i] if current_node is not None: # inserting_left == 1 when inserting a left child node # inserting_left == 0 when inserting a right child node inserting_left = i & 1 # if a tree node has an indice i (0-indexed) in list, the parent node indice will be (i + 1) // 2 - 1 (0-indexed) current_parent_node = node_queue[(i + 1) // 2 - 1] if inserting_left: current_parent_node.insert_left_child(current_node) else: current_parent_node.insert_right_child(current_node) i += 1 self._depth = self._root.height() self._size = self._root.size() return self._root
def sortedListToBST(self, head: ListNode) -> TreeNode: if not head: return None elif not head.next: return TreeNode(head.val) else: slow = fast = head pre = None while fast and fast.next: pre = slow slow = slow.next fast = fast.next.next node = TreeNode(slow.val) pre.next = None node.left = self.sortedListToBST(head) node.right = self.sortedListToBST(slow.next) return node
def buildTree(self, inorder, postorder): """ :type inorder: List[int] :type postorder: List[int] :rtype: TreeNode """ def find(l, v): for index, ele in enumerate(l): if ele == v: return index return -1 if len(postorder) == 0 or len(inorder) == 0: return None node = TreeNode(postorder[-1]) index = find(inorder, postorder[-1]) node.left = self.buildTree(inorder[:index], postorder[:index]) node.right = self.buildTree(inorder[index + 1:], postorder[index:-1]) return node
def binary_tree(array: List) -> Union[TreeNode, None]: """return the binary tree represented in array using preorder traversal order. For example [1, 2, 4, None, None, 5, None, None, 3, None, None] returns the following tree: 1 / \ 2 3 / \ 4 5 Args: array (List, optional): array representation of the output binary tree. Defaults to []. Returns: Union[TreeNode, None]: root node of the binary tree. """ if len(array) == 0: return None root = TreeNode(val=array[0]) path = [root] goLeft = [True] for x in array[1:]: currentNode = path[-1] if x is None: if goLeft[-1]: goLeft[-1] = False else: goLeft.pop() path.pop() while ((len(path) > 0) and (not goLeft[-1]) and (path[-1].right is not None)): goLeft.pop() path.pop() else: if goLeft[-1]: currentNode.left = TreeNode(val=x) path.append(currentNode.left) goLeft[-1] = False goLeft.append(True) else: currentNode.right = TreeNode(val=x) path.append(currentNode.right) goLeft.append(True) return root
def flatten(self, root: TreeNode) -> None: """ Do not return anything, modify root in-place instead. """ if root: stack = [root] dummy = TreeNode(None) cur = dummy while stack: node = stack.pop() cur.right = node cur = node for c in (node.right, node.left): if c: stack.append(c) cur.left = None
def test_insert_root(self): """ Tests inserting new root node """ new_root = TreeNode(-1, 0) self.binary_tree.insert_root(new_root) self.assertEqual(7, self.binary_tree.size()) self.assertEqual(4, self.binary_tree.depth()) self.assertEqual(-1, self.binary_tree.root().data()) self.assertEqual([(-1, 4, 0), (0, 3, 1), None, (1, 2, 2), (2, 2, 2), None, None, None, (4, 1, 3), None, (6, 1, 3), None, None, None, None, None, None, (7, 0, 4)], self.binary_tree._level_order_traversal())
def build_tree(self, input_data): n = len(input_data) if n == 0: return None self.list_node = [] for data in input_data: if data: self.list_node.append(TreeNode(data)) else: self.list_node.append(None) child_index = 1 for i in range(n): if self.list_node[i] != None: try: self.list_node[i].left = self.list_node[child_index] child_index += 1 self.list_node[i].right = self.list_node[child_index] child_index += 1 except: break return self.list_node[0]
class BinaryTree(object): def __init__(self, root=None): """ Constructor Args: root (TreeNode): root node """ self._root = root self._depth, self._size = 0, 0 if root is not None: # if non-trival root node is given # maintain tree depth and size self._depth = root.height() self._size = root.size() def size(self): """ Returns size """ return self._size def depth(self): """ Returns depth """ return self._depth def copy_from_iterable(self, iterable): """ Copies data from iterable, which are put into the binary tree in level order Args: iterable (iterable): iterable object from which contents are copied and put into binary tree Returns: root node of the binary tree """ # initialize root node self._root = TreeNode(iterable[0], 0) iterable_size = len(iterable) # create a list of tree nodes with each saving data from iterable # but topoligical relation has not been established yet # note that nodes saved in iterable are mapped to binary tree node in level order node_queue = [self._root] for i, data in enumerate(iterable[1:]): inserting_right = i & 1 node_queue.append( TreeNode(data, -1 if inserting_right else 1) if data else None) i = 1 while i < iterable_size: current_node = node_queue[i] if current_node is not None: # inserting_left == 1 when inserting a left child node # inserting_left == 0 when inserting a right child node inserting_left = i & 1 # if a tree node has an indice i (0-indexed) in list, the parent node indice will be (i + 1) // 2 - 1 (0-indexed) current_parent_node = node_queue[(i + 1) // 2 - 1] if inserting_left: current_parent_node.insert_left_child(current_node) else: current_parent_node.insert_right_child(current_node) i += 1 self._depth = self._root.height() self._size = self._root.size() return self._root def is_full_binary_tree(self): """ Returns if the binary tree is a full binary tree """ return self._size == 2**(self._depth + 1) - 1 def root(self): """ Returns root node of the binary tree """ return self._root def empty(self): """ Returns if the binary tree is empty """ return self._size == 0 def insert_root(self, new_root): """ Inserts a new root node to the binary tree Args: new_root (TreeNode): new root node to be inserted """ # check if the given new root node is valid if new_root.is_root(): # if given new root node already has left(right) child, # insert the binary tree as right(left) child if not new_root.has_left_child(): new_root.insert_left_child(self.root()) elif not new_root.has_right_child(): new_root.insert_right_child(self.root()) else: raise ValueError('the given root node has child node') # update root, size and depth self._root = new_root self._size = new_root.size() self._depth = new_root.height() def insert_left_subtree(self, left_subtree_root, left_subtree): """ Inserts given binary tree (including it's root) to given tree node as left child Args: left_subtree_root (TreeNode): insert given binary tree to this tree node left_subtree (BinaryTree): insert this binary tree to given tree node as left child """ left_subtree_root.insert_left_child(left_subtree.root()) self._size = self._root.size() self._depth = self._root.height() def insert_right_subtree(self, right_subtree_root, right_subtree): """ Inserts given binary tree (including it's root) to given tree node as right child Args: right_subtree_root (TreeNode): insert given binary tree to this tree node right_subtree (BinaryTree): insert this binary tree to given tree node as right child """ right_subtree_root.insert_right_child(right_subtree.root()) self._size = self._root.size() self._depth = self._root.height() def get_lowest_leaf(self, starting_node=None): """ Gets lowest leaf node below given starting node If starting node is given, it's equivalent to fetch the lowest leaf in subtree rooted at starting node. Args: starting_node (TreeNode): the tree node below which the lowest leaf is retrieved """ # default to root node if starting_node is None: starting_node = self._root lowest_leaf = starting_node stack = [starting_node] while len(stack): node = stack.pop() # if a lower node is found, update the lowest leaf if node.height() < lowest_leaf.height(): lowest_leaf = node if node.has_left_child(): stack.append(node.left_child()) if node.has_right_child(): stack.append(node.right_child()) return lowest_leaf def remove_subtree(self, subtree_root): """ Removes subtree from current binary tree Args: subtree_root (TreeNode): root node of subtree to be removed """ # remove all descendant nodes below the subtree root node subtree_root.clear_descendant() # get the parent node of subtree root in original binary tree subtree_root_parent = subtree_root.parent() if subtree_root_parent is None: self.__init__(root=None) return # reset the child node of the parent node of subtree root if subtree_root.is_left_child(): subtree_root_parent._left_child = None else: subtree_root_parent._right_child = None # release memory del subtree_root # since the structure changes for the subtree rooted at subtree_root_parent, # update height/size of each node in this specific subtree lowest_leaf = self.get_lowest_leaf(subtree_root_parent) lowest_leaf.update_height_from_child() lowest_leaf.update_ancestor_height() subtree_root_parent.update_size() subtree_root_parent.update_ancestor_size() self._size = self._root.size() self._depth = self._root.height() def split_subtree(self, subtree_root): """ Splits the subtree rooted at given node from the binary tree Args: subtree_root (TreeNode): root node of subtree to be splitted """ # remove all descendant nodes below the subtree root node new_leaf_node = subtree_root.parent() # make subtree_root a root node subtree_root._parent = None # reset the child node of the parent node of subtree root if subtree_root.is_left_child(): new_leaf_node._left_child = None else: new_leaf_node._right_child = None new_leaf_node.update_size() new_leaf_node.update_ancestor_size() # update the tree left after the split lowest_leaf = self.get_lowest_leaf(new_leaf_node) lowest_leaf.update_height_from_child() lowest_leaf.update_ancestor_height() self._size = self._root.size() self._depth = self._root.height() # update depth/height of each node in splitted subtree subtree_root._node_type = 0 subtree_root.update_depth() subtree_root.update_descendant_depth() lowest_leaf = self.get_lowest_leaf(subtree_root) lowest_leaf.update_height_from_child() lowest_leaf.update_ancestor_height() return subtree_root def preorder_traversal(self, starting_node=None): """ Traverse the binary tree in pre-order: parent node -> left child -> right child Args: starting_node (TreeNode): traverse the subtree rooted at given starting node Returns: data_array (list): list of data saved in binary tree """ data_array = [] if starting_node is None: starting_node = self._root stack = Stack() current_node = starting_node while True: while current_node is not None: data_array.append(current_node.data()) # push right child node into stack if it exists stack.push(current_node.right_child()) # always go along left child current_node = current_node.left_child() if stack.empty(): break current_node = stack.pop() return data_array def inorder_traversal(self, starting_node=None): """ Traverse the binary tree in in-order: left child -> parent node -> right child Args: starting_node (TreeNode): traverse the subtree rooted at given starting node Returns: data_array (list): list of data saved in binary tree """ data_array = [] if starting_node is None: starting_node = self._root stack = Stack() current_node = starting_node while True: while current_node is not None: stack.push(current_node) # always go along left child current_node = current_node.left_child() if stack.empty(): break current_node = stack.pop() data_array.append(current_node.data()) current_node = current_node.right_child() return data_array def _to_highest_leftmost_leaf(self, node_stack): """ Goes to the highest leftmost leaf node visible from left while adding node on path to given stack Args: node_stack (Stack): containing nodes traveled when going to the highest leftmost leaf node visible from left """ top_node = node_stack.top() while top_node is not None: # in order to get leftmost leaf, always check left subtree first if top_node.has_left_child(): if top_node.has_right_child(): node_stack.push(top_node.right_child()) node_stack.push(top_node.left_child()) else: # only if no left subtree available node_stack.push(top_node.right_child()) top_node = node_stack.top() node_stack.pop() def postorder_traversal(self, starting_node=None): """ Traverses the binary tree in post-order: left child -> right child -> parent node Args: starting_node (TreeNode): traverse the subtree rooted at given starting node Returns: data_array (list): list of data saved in binary tree """ data_array = [] if self._root is None: return data_array if starting_node is None: starting_node = self._root stack = Stack() current_node = starting_node stack.push(current_node) while not stack.empty(): top_node = stack.top() if top_node != current_node.parent(): self._to_highest_leftmost_leaf(stack) current_node = stack.pop() data_array.append(current_node.data()) return data_array def _level_order_traversal(self, starting_node=None, include_none=True): """ Traverses the binary tree from top level to bottom and saves data/height/depth for testing purpose Args: starting_node (TreeNode): traverse the subtree rooted at given starting node include_none (bool): True if including None node in binary tree Returns: data_array ([3-tuple]): [(data saved in node, height, depth)] """ data_array = [] # returns empty list if the binary tree is empty if self._root is None: return data_array # traverse from root if starting node is not given if starting_node is None: starting_node = self._root queue = Queue() # (data, height, depth, left child, right child) queue.enqueue((starting_node.data(), starting_node.height(), starting_node.depth(), starting_node.left_child(), starting_node.right_child())) while not queue.empty(): top_node = queue.dequeue() if top_node[0] is not None: # if it's a non-trival node, append data/height/depth data_array.append((top_node[0], top_node[1], top_node[2])) else: data_array.append(None) # if the node is not on the deepest level, left and right child can be added into queue and visited soon if top_node[2] < self.depth(): top_node_left_child, top_node_right_child = top_node[ 3], top_node[4] entry = [None, top_node[1] - 1, top_node[2] + 1, None, None] if top_node_left_child is not None: entry[0] = top_node_left_child.data() entry[3] = top_node_left_child.left_child() entry[4] = top_node_left_child.right_child() queue.enqueue(tuple(entry)) entry = [None, top_node[1] - 1, top_node[2] + 1, None, None] if top_node_right_child is not None: entry[0] = top_node_right_child.data() entry[3] = top_node_right_child.left_child() entry[4] = top_node_right_child.right_child() queue.enqueue(tuple(entry)) # if include_none == False, filter out the None element if not include_none: data_array = list(filter(lambda x: x is not None, data_array)) # remove all None at the end of list since they are trival and not informative while data_array[-1] is None: data_array.pop() return data_array def level_order_traversal(self, starting_node=None, include_none=True): """ Traverses the binary tree from top level to bottom Args: starting_node (TreeNode): traverse the subtree rooted at given starting node include_none (bool): True if including None node in binary tree Returns: data_array ([object]): [data saved in node] """ data_array = self._level_order_traversal(starting_node, include_none) if include_none: data_array = [ data[0] if data is not None else None for data in data_array ] else: data_array = list(filter(lambda x: x is not None, data_array)) data_array = [data[0] for data in data_array] return data_array
# @param root, a tree node # @return an integer def maxDepth(self, root): if not bool(root): return 0 if root.left == None: if root.right == None: return 1 else: return 1 + self.maxDepth(root.right) elif root.right == None: if root.left == None: return 1 else: return 1 + self.maxDepth(root.left) else: return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) testRoot = TreeNode(5) testRoot.left = TreeNode(3) testRoot.right = TreeNode(8) testRoot.left.left = TreeNode(2) testRoot.left.right = TreeNode(4) testRoot.right.left = TreeNode(7) testRoot.right.left.left = TreeNode(6) sol = Solution() print sol.maxDepth(testRoot) print sol.maxDepth({})
def isValidBST(self, root: TreeNode) -> bool: if root: self.pre = TreeNode(-2**32) return self.postOrderTraverse(root) else: return True
# @param q, a tree node # @return a boolean def isSameTree(self, p, q): if not bool(p): if not bool(q): return True else: return False if not bool(q): if not bool(p): return True else: return False if p.val == q.val: return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) else: return False sol = Solution() print sol.isSameTree({}, {0}) pTree = TreeNode(2) pTree.left = TreeNode(1) pTree.right = TreeNode(3) qTree = TreeNode(2) qTree.left = TreeNode(1) qTree.right = TreeNode(3) print sol.isSameTree(pTree, qTree)
sums.append(self.dfsSum(root.left, root.val)) if root.right != None: sums.append(self.dfsSum(root.right, root.val)) return sum(sums) def dfsSum(self, root, cursum): ret = [] cursum = cursum * 10 + root.val if not root.left and not root.right: return cursum if root.left != None and root.right != None: return self.dfsSum(root.left, cursum) + self.dfsSum(root.right, cursum) if root.left != None and not root.right: return self.dfsSum(root.left, cursum) if root.right != None and not root.left: return self.dfsSum(root.right, cursum) sol = Solution() t = TreeNode(8) t.left = TreeNode(3) t.right = TreeNode(5) t.left.right = TreeNode(9) t.left.right.left = TreeNode(9) t.left.right.right = TreeNode(5) print sol.sumNumbers(t)