def main():
    import utils
    root = utils.build_binary_tree([1, 2, 2, 3, None, None, 3, 4, None, None, 4])

    print(Solution().isBalanced(root))

    root = utils.build_binary_tree([1])
    print(Solution().isBalanced(root))

    print(Solution().isBalanced(None))
def main():
    solver = Solution()
    tests = [
        ((build_binary_tree([1,2,2]),),True ),
        ((build_binary_tree([1,2,2,None,3,None,3]),),False)
    ]
    for params, expect in tests:
        print('-' * 5 + 'TEST' + '-' * 5)
        print('Input:  ' + str(params))
        print('Expect: ' + str(expect))

        result = solver.isSymmetric(*params)
        print('Result: ' + str(result))
    pass
def main():
    solver = Solution()
    from utils import build_binary_tree
    tree = build_binary_tree([1,2,3,4,5,None, 7])
    print(tree)
    solver.connect(tree)
    print(tree)
    pass
def main():
    solver = Solution()
    from utils import build_binary_tree
    tests = [
        ((build_binary_tree([1,2,3]),), 25),
    ]
    for params, expect in tests:
        print('-' * 5 + 'TEST' + '-' * 5)
        print('Input:  ' + str(params))
        print('Expect: ' + str(expect))

        result = solver.sumNumbers(*params)
        print('Result: ' + str(result))
    pass
        :rtype: List[List[str]]
        """

        def get_depth(node: TreeNode):
            if node is None:
                return 0
            else:
                return 1 + max(get_depth(node.left), get_depth(node.right))

        depth = get_depth(root)
        mat = [["" for _ in range(2 ** depth - 1)] for _ in range(depth)]

        def print_node(node: TreeNode, row, col: int):
            if node is None:
                return
            # print(row, col, node.val)
            mat[row - 1][col - 1] = str(node.val)
            print_node(node.left, row + 1, col - 2 ** (depth - row - 1))
            print_node(node.right, row + 1, col + 2 ** (depth - row - 1))

        print_node(root, 1, 2 ** (depth - 1))
        return mat
        # return '\n'.join(' '.join(line) for line in mat)


if __name__ == '__main__':
    sol = Solution()
    print(sol.printTree(build_binary_tree([1, 2])))
    print(sol.printTree(build_binary_tree([1, 2, 3, None, 4])))
    print(sol.printTree(build_binary_tree([1, 2, 5, 3, None, None, None, 4])))
# Show Tags
# 
# Tree
# Depth-first Search


# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

from utils import TreeNode, build_binary_tree

print(build_binary_tree([1, 2, 3, None, None, 4, None, None, 5]))


class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """

        def rotate(node):
            if node is not None:
                node.left, node.right = rotate(node.right), rotate(node.left)
            return node

        def is_same(node1, node2):
    2. The BST is always valid, each node's value is an integer, and each node's
       value is different.
'''
'''
总结:

    1. 二叉搜索树的中序遍历结果就是一个升序数组,所以相邻两数之间可能存在最小差值
'''

EXAMPLES = [
    (
        build_binary_tree(*[
            90,
            69,
            None,
            49,
            89,
            None,
            52,
        ]),
        1,
    ),
]
'''
         90
        /
      69
     /  \
   49    89
     \
     52
Example #8
0
Example 1:

        1
      /   \
     0     1
    / \   / \
   0   1 0   1

Input: [1, 0, 1, 0, 1, 0, 1]
Output: 22
Explanation: (100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22
'''

EXAMPLES = [
    (build_binary_tree(*[1, 0, 1, 0, 1, 0, 1]), 22),
]


class Solution:
    def get_values(self, root: TreeNode) -> List[str]:
        r = []
        if root:
            if root.left is None and root.right is None:
                r.append(str(root.val))

            if root.left:
                left = self.get_values(root.left)
                if left:
                    r += [str(root.val) + l for l in left]
Example #9
0
         3   5

Example 2:

Input: root = [6, 2, 8, 0, 4, 7, 9, null, null, 3, 5], p = 2, q = 4
Output: 2
Explation: 结点 2 和结点 4 的最近公共祖先是 2,因为根据定义最近公共祖先结点可以为结点本身。
'''
'''
总结:

    1. 深度尽可能大,表示它距离两个结点尽可能近。
    2. 二叉搜索树导致每个结点都有通往根结点的唯一路径,不同的结点之间路径存在重合的部分。
'''

BINARY_TREE_NODE = build_binary_tree(*[6, 2, 8, 0, 4, 7, 9, None, None, 3, 5])

EXAMPLES = [(
    (
        BINARY_TREE_NODE,
        BINARY_TREE_NODE.left,
        BINARY_TREE_NODE.right,
    ),
    BINARY_TREE_NODE,
),
            (
                (
                    BINARY_TREE_NODE,
                    BINARY_TREE_NODE.left,
                    BINARY_TREE_NODE.left.right,
                ),
       / \
      3   3
     / \
    4   4

    return false.
'''
'''
总结:

    1. 是否平衡取决于某节点左子树高度与右子树高度相差最多为1,也就是
       left_height - right_height in [-1, 0, 1]
'''

EXAMPLES = [(
    build_binary_tree(*[1, None, 2, None, 3]),
    False,
), (
    build_binary_tree(3, 9, 20, None, None, 15, 7),
    True,
), (
    build_binary_tree(*[1, 2, 2, 3, 3, None, None, 4, 4]),
    False,
), (
    build_binary_tree(*[1, 2, 2, 3, None, None, 3, 4, None, None, 4]),
    False,
)]


class Solution:
    def get_depth_from_node(self, node: TreeNode) -> int:
Example:

Given binary tree [3, 9, 20, null, null, 15, 7]

     3
    / \
   9   20
      /  \
     15   7

return its depth = 3
'''

EXAMPLES = [
    (build_binary_tree(*[3, 9, 20, None, None, 15, 7]), 3),
]


class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        depth = 0
        if root:
            left_depth = 0
            if root.left:
                left_depth += self.maxDepth(root.left)

            right_depth = 0
            if root.right:
                right_depth += self.maxDepth(root.right)
        except ValueError:
            return TreeNode(int(data))

        right_bound = 0
        counter = 0
        while right_bound < len(data):
            if data[right_bound] == '(':
                counter += 1
            elif data[right_bound] == ')':
                counter -= 1
                if counter == 0:
                    right_bound += 1
                    break
            right_bound += 1
        val = int(data[:left_bound])
        left_data = data[left_bound+1:right_bound-1]
        right_data = data[right_bound+1:-1]
        node = TreeNode(val)
        node.left = self.deserialize(left_data)
        node.right = self.deserialize(right_data)
        return node


# Your Codec object will be instantiated and called as such:
root = build_binary_tree([1, 2, 3, 4, 5, 6])
codec = Codec()
s = codec.serialize(root)
print(s)
print(codec.deserialize("1(2)(3)"))
print(codec.deserialize(s))
But the following [1, 2, 2, null, 3, null, 3] is not:

      1
    /   \
   2     2
    \     \
     3     3
'''

EXAMPLES = [
    (
        None,
        True,
    ),
    (
        build_binary_tree(*[1, 2, 2, 3, 4, 4, 3]),
        True,
    ),
    (
        build_binary_tree(*[1, 2, 2, None, 3, None, 3]),
        False,
    ),
    (
        build_binary_tree(*[1, 2, 2, None, 3, None, 3]),
        False,
    ),
]
'''
总结:

   1. 某节点的左子树互换位置后与右子树一致,就是队称二叉树

class Solution:
    def widthOfBinaryTree(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if root is None:
            return 0
        from collections import defaultdict, deque
        levels = defaultdict(set)
        # levels[0].add(0)
        queue = deque()
        queue.append((0, 0, root))
        while queue:
            depth, idx, node = queue.popleft()
            levels[depth].add(idx)
            if node.left:
                queue.append((depth + 1, idx * 2, node.left))
            if node.right:
                queue.append((depth + 1, idx * 2 + 1, node.right))
        return max(max(row) - min(row) + 1 for row in levels.values())


if __name__ == '__main__':
    from utils import build_binary_tree

    sol = Solution().widthOfBinaryTree
    print(sol(build_binary_tree([1, 2, 3, 4, None, None, 5])))
The binary search tree is guaranteed to have unique values.

Example 1:

    Input: root = [10, 5, 15, 3, 7, null, 18], L = 7, R = 15
    Output: 32

Example 2:

    Input: root = [10, 5, 15, 3, 7, 13, 10, 1, null, 6], L = 6, R = 10
    Output: 23
'''

EXAMPLES = [
    (
        (build_binary_tree(*[10, 5, 15, 3, 7, None, 18]), 7, 15),
        32,
    ),
    (
        (build_binary_tree(*[10, 5, 15, 3, 7, 13, 18, 1, None, 6]), 6, 10),
        23,
    ),
]


class Solution:
    def rangeSumBST(self, root: TreeNode, L: int, R: int) -> int:
        sum = 0
        if root:
            if root.left:
                sum += self.rangeSumBST(root.left, L, R)
Example #16
0
         2   3      2   3

Output: true

Exmalpe 2:

Input:    1           1
         /             \
        2               2

Output: false
'''

EXAMPLES = [
    (
        (build_binary_tree(*[1, 2, 3]), build_binary_tree(*[1, 2, 3])),
        True,
    ),
    (
        (build_binary_tree(*[1, 2]), build_binary_tree(*[1, None, 2])),
        False,
    ),
]


class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        r = p is not None and q is not None if p or q else True
        if p and q:
            r = p.val == q.val
            if r:

class Solution:
    def findSecondMinimumValue(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        vals = []
        lower = root.val

        def search(node: TreeNode):
            if node is None:
                return
            elif node.val > lower:
                vals.append(node.val)
            elif node.val == lower:
                search(node.left)
                search(node.right)

        search(root)
        return min(vals, default=-1)


if __name__ == '__main__':
    sol = Solution()
    print(sol.findSecondMinimumValue(TreeNode(2)))
    print(sol.findSecondMinimumValue(build_binary_tree([2, 2, 5, None, None, 5, 7])))
    print(sol.findSecondMinimumValue(
        build_binary_tree([2, 2, 2])))
总结:

    1. 最小深度是根结点到最近叶子结点的深度,不包括根结点本身。
    2. 根结点如果存在左右子树,


         -9
        /   \
      -3     2
        \   / \
         4 4   0
        /  /
       -6  -5
'''

EXAMPLES = [(build_binary_tree(*[3, 9, 20, None, None, 15, 7]), 2),
            (build_binary_tree(*[1, 2]), 2),
            (build_binary_tree(*[-9, -3, 2, None, 4, 4, 0, -6, None, -5]), 3)]


class Solution:
    def minDepth(self, root: TreeNode) -> int:
        r = 0
        if root:
            r += 1

            left_depth = self.minDepth(root.left)
            right_depth = self.minDepth(root.right)

            if left_depth and right_depth:
                r += min(left_depth, right_depth)
Example #19
0
   1
 /   \
2     3
 \
   5


Ouput: ['1->2->5', '1->3']

Explanation: All root-to-leaf paths are: 1->2->5, 1->3
'''

EXAMPLES = [
    (
        build_binary_tree(*[1, 2, 3, None, 5]),
        ['1->2->5', '1->3'],
    ),
]


class Solution:
    def get_tree_paths(self, root: TreeNode) -> List[List[str]]:
        nodes = []
        if root:
            if root.left is None and root.right is None:
                nodes.append([str(root.val)])
            else:
                left_results = self.get_tree_paths(root.left)
                if left_results:
                    nodes += [[str(root.val)] + l for l in left_results]
Example #20
0
       2
     /   \
    0     3
   / \
  -4  1
'''
'''
总结:

    1. greater 是一个不断遍历不断累加的值
'''

EXAMPLES = [
    # (build_binary_tree(*[5, 2, 13]), build_binary_tree(*[18, 20, 13])),
    (build_binary_tree(*[2, 0, 3, -4, 1]),
     build_binary_tree(*[[5, 6, 3, 2, 6]])),
]


class Solution:
    def greater_tree(self, root: TreeNode, greater: int) -> TreeNode:
        if root:
            if root.right:
                greater = self.greater_tree(root.right, greater)

            root.val = root.val + greater
            greater = root.val

            if root.left:
                greater = self.greater_tree(root.left, greater)
class Solution:
    def trimBST(self, root, L, R):
        """
        :type root: TreeNode
        :type L: int
        :type R: int
        :rtype: TreeNode
        """

        def go(node: TreeNode) -> TreeNode:
            if node is None:
                return None
            if node.val < L:
                return go(node.right)
            elif node.val > R:
                return go(node.left)
            else:
                node.left = go(node.left)
                node.right = go(node.right)
            return node

        return go(root)


if __name__ == '__main__':
    sol = Solution()
    print(sol.trimBST(build_binary_tree([1, 0, 2]), 1, 2))
    print(sol.trimBST(build_binary_tree([1, 0, 2]), 3, 3))
    print(sol.trimBST(build_binary_tree([3, 0, 4, None, 2, None, None, 1]), 1, 3))
        :rtype: bool
        """

        def find(node: TreeNode, target: int) -> bool:
            if node is None:
                return False
            elif node.val == target:
                return True
            elif node.val < target:
                return find(node.right, target)
            elif node.val > target:
                return find(node.left, target)

        def go(node: TreeNode):
            return (node is not None
                    and ((node.val * 2 != k
                          and find(root, k - node.val))
                         or go(node.left)
                         or go(node.right)))

        return go(root)


if __name__ == '__main__':
    sol = Solution()
    tree = build_binary_tree([5, 3, 6, 2, 4, None, 8])
    print(sol.findTarget(tree, 10))
    print(sol.findTarget(tree, 12))
    print(sol.findTarget(tree, 16))
    print(sol.findTarget(tree, 28))
'''
'''
总结:

    1. 前序遍历,target = sum - node.val,分别从左子树和右子树中寻找新的路径。
    2. 左右子树均有可能找出符合要求的路径
    3. 符合要求的答案中,可能还存在余下节点和为 0 的情况,这种情况是一个新的正确路径
'''

EXAMPLES = [
    # (
    #     (build_binary_tree(*[10, 5, -3, 3, 3, None, 11, 3, -2, None, 1]), 8),
    #     3,
    # ),
    ((build_binary_tree(*[1, -2, -3, 1, 3, -2, None, -1]), -1), 4)
]


class Solution:
    def path_sum(self, node: TreeNode, sum: int) -> List[TreeNode]:
        count = 0
        if node:
            target = sum - node.val
            if target == 0:
                count += 1

            count += self.path_sum(node.left, target)
            count += self.path_sum(node.right, target)

        return count