def allPossibleFBT(N): table = [[]] + [[TreeNode(0)]] + [[] for _ in range(N)] #if N < 3: # return table[N] for i in range(3, N + 1): # List of possible FBTs for `i` nodes, solves subproblem for N=i res = [] # Iterate through all possible pairs of left/right idxs # Previous smaller subproblem solved and memoised in table for leftIdx in range(1, i - 1): # Require that leftIdx + rightIdx + 1 (root) = i rightIdx = i - 1 - leftIdx lefts = table[leftIdx] rights = table[rightIdx] for left in lefts: for right in rights: # Build node and add ro root = TreeNode(0) root.left = left root.right = right res.append(root) table[i] = res return table[N]
def sortedListToBST(head): # base case: empty list if head is None: return None # base case: singleton list if head.next is None: return TreeNode(head.val) # use tortoise-hare algorithm to find midpoint, keeping track of mid's prev prev, left, right = None, head, head while right.next: # advance left pointer prev = left left = left.next # advance right pointer right = right.next if right.next is None: break right = right.next # partition w.r.t. midpoint defined by left prev.next = None # recursively build children leftChild = sortedListToBST(head) rightChild = sortedListToBST(left.next) # create, setup and return root node root = TreeNode(left.val) root.left = leftChild root.right = rightChild return root
def addOneRow(root, val, depth): # base case: empty tree, nothing to do if root is None: return root # base case: insert at root depth, # put current root as left subtree of new root as per spec if depth == 1: newRoot = TreeNode(val) newRoot.left = root return newRoot # setup level order traversal lvlToModify = depth - 1 queue = deque([(root, 1)]) while queue: node, lvl = queue.popleft() if lvl < lvlToModify: # add children as required if node.left: queue.append((node.left, lvl + 1)) if node.right: queue.append((node.right, lvl + 1)) else: # insert new row here newLeft = TreeNode(val) newLeft.left = node.left node.left = newLeft newRight = TreeNode(val) newRight.right = node.right node.right = newRight return root
def rangeSumBST(root, L, R): if not root: return 0 val = root.val if val < L: return rangeSumBST(root.right, L, R) if val > R: return rangeSumBST(root.left, L, R) leftSum = rangeSumBST(root.left, L, R) rightSum = rangeSumBST(root.right, L, R) return leftSum + rightSum + val if __name__ == "__main__": root = TreeNode(10) root.left = TreeNode(5) root.right = TreeNode(15) root.left.left = TreeNode(3) root.left.right = TreeNode(7) root.right.right = TreeNode(18) print(root) print("Enter space-separated range <L> <R>: ", end="") L, R = list(map(int, input().strip().split())) res = rangeSumBST(root, L, R) print(res)
curr = p while curr: seen.add(curr.val) curr = parents[curr.val] # backtrack path to root from q # first node that was seen in the previous backtrack is LCA res = q while res.val not in seen: res = parents[res.val] return res if __name__ == "__main__": root = TreeNode(3) p = root.left = TreeNode(5) q = root.right = TreeNode(1) root.left.left = TreeNode(6) root.left.right = TreeNode(2) root.left.right.left = TreeNode(7) root.left.right.right = TreeNode(4) root.right.left = TreeNode(0) root.right.right = TreeNode(8) print("Tree:") print(root) print() print("p: {}".format(p.val))
while queue: curr, depth = queue.popleft() # enqueue children if they exist if curr.left: queue.append((curr.left, depth + 1)) if curr.right: queue.append((curr.right, depth + 1)) # reset lvlNodes list if crossing depth boundary if depth > currLvl: currLvl = depth res.append(lvlNodes) lvlNodes = [] lvlNodes.append(curr.val) if lvlNodes: res.append(lvlNodes) return res if __name__ == "__main__": root = TreeNode(3) root.left = TreeNode(9) root.right = TreeNode(20) root.right.left = TreeNode(15) root.right.right = TreeNode(7) print(root) nodes = levelOrder(root) print(nodes)
return empty_left and empty_right # Base case: root node is different, return False if root1.val != root2.val: return False r1_left = root1.left r1_right = root1.right r2_left = root2.left r2_right = root2.right return (flipEquiv(r1_left, r2_right) and flipEquiv(r1_right, r2_left)) or (flipEquiv(r1_left, r2_left) and flipEquiv(r1_right, r2_right)) if __name__ == "__main__": root1 = TreeNode(1) root1.left = TreeNode(2) root1.right = TreeNode(3) root2 = TreeNode(1) root2.left = TreeNode(3) root2.right = TreeNode(2) print("1: {}".format(root1)) print("2: {}".format(root2)) print(flipEquiv(root1, root2)) root2.right = TreeNode(3) print("2: {}".format(root2)) print(flipEquiv(root1, root2))
newRoot = increasingBST(root.left) # put `root` as rightmost child of `newRoot` root.left = None curr = newRoot while curr.right: curr = curr.right curr.right = root root.right = increasingBST(root.right) return newRoot if __name__ == "__main__": root = TreeNode(5) root.left = TreeNode(3) root.right = TreeNode(6) root.left.left = TreeNode(2) root.left.right = TreeNode(4) root.left.left.left = TreeNode(1) root.right.right = TreeNode(8) root.right.right.left = TreeNode(7) root.right.right.right = TreeNode(9) print(root) newRoot = increasingBST(root) print(newRoot)
""" def pruneTree(root): # base case: empty tree if root is None: return root # recursive calls to prune children root.left = pruneTree(root.left) root.right = pruneTree(root.right) # evaluate whether current node should be pruned by 2nd base case if root.val == 0 and root.left is None and root.right is None: return None return root if __name__ == "__main__": root = TreeNode(1) root.right = TreeNode(0) root.right.left = TreeNode(0) root.right.right = TreeNode(1) print("Before pruning:") print(root) root = pruneTree(root) print() print("After pruning:") print(root)
return getLeaves(root1) == getLeaves(root2) def getLeaves(root): # base case: empty tree if root is None: return [] # base case: leaf if root.left is None and root.right is None: return [root.val] return getLeaves(root.left) + getLeaves(root.right) if __name__ == "__main__": root1 = TreeNode(3) root1.left = TreeNode(5) root1.right = TreeNode(7) root2 = TreeNode(10) root2.left = TreeNode(1) root2.left.left = TreeNode(5) root2.right = TreeNode(7) print("Tree 1: {}".format(root1)) print("Tree 2: {}".format(root2)) similar = leafSimilar(root1, root2) print("Both trees are{} leaf similar.".format("" if similar else " not"))
res.append(path) # add children to queue # tree can contain negative numbers so cannot "shortcircuit" # if sumSoFar already exceeds target (since val could be negative) if node.left: queue.append((node.left, path + [node.left.val], sumSoFar + node.left.val)) if node.right: queue.append((node.right, path + [node.right.val], sumSoFar + node.right.val)) return res if __name__ == "__main__": root = TreeNode(5) root.left = TreeNode(4) root.right = TreeNode(8) root.left.left = TreeNode(11) root.left.left.left = TreeNode(7) root.left.left.right = TreeNode(2) root.right.left = TreeNode(13) root.right.right = TreeNode(4) root.right.right.left = TreeNode(5) root.right.right.right = TreeNode(1) print("Tree:") print(root) print() print("Enter target: ", end="")
return 0 subtreeSum = getSum(node.left) + getSum(node.right) + node.val if subtreeSum in sumFreqTable: sumFreqTable[subtreeSum] += 1 else: sumFreqTable[subtreeSum] = 0 # update highest frequency accumulator freq = sumFreqTable[subtreeSum] if freq > highestFreq: highestFreq = freq res = [subtreeSum] elif freq == highestFreq: res.append(subtreeSum) return subtreeSum getSum(root) return res if __name__ == "__main__": root = TreeNode(5) root.left = TreeNode(2) root.right = TreeNode(-5) print(root) sums = findFrequentSubtreeSum(root) print(sums)