예제 #1
0
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]
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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)
예제 #5
0
    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))
예제 #6
0
    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)
예제 #7
0
    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))
예제 #8
0
        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)
예제 #9
0
"""
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)
예제 #10
0
    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"))
예제 #11
0
        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="")
예제 #12
0
            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)