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 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]
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)
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)
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]
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