def copy(self, source: TreeNode) -> TreeNode: if not source: return source res = TreeNode(source.val) res.left = self.copy(source.left) res.right = self.copy(source.right) return res
def build(self, values, index, n): if index <= n and index in values: node = TreeNode(values[index]) node.left = self.build(values, 2 * index + 1, n) node.right = self.build(values, 2 * index + 2, n) return node else: return None
def insert(self, root: TreeNode, num: int) -> TreeNode: if not root: return TreeNode(num) if num < root.val: root.left = self.insert(root.left, num) else: root.right = self.insert(root.right, num) return root
def __buildTree(self, inorder, postorder, idx_itr): if not inorder: return None pidx = next(idx_itr) root = TreeNode(postorder[pidx]) idx = inorder.index(postorder[pidx]) root.right = self.__buildTree(inorder[idx + 1:], postorder, idx_itr) root.left = self.__buildTree(inorder[:idx], postorder, idx_itr) return root
def sorted_array_to_bst(nums: list[int]) -> Optional[TreeNode]: if not nums: return None middle = len(nums) // 2 root = TreeNode(nums[middle]) root.left = sorted_array_to_bst(nums[:middle]) root.right = sorted_array_to_bst(nums[middle + 1 :]) return root
def build_tree(preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: if not inorder: return None mid = inorder.index(preorder[0]) root = TreeNode(preorder[0]) if len(inorder) > 1: root.left = build_tree(preorder[1 : mid + 1], inorder[:mid]) root.right = build_tree(preorder[mid + 1 :], inorder[mid + 1 :]) return root
def delete(self, root: TreeNode, num: int) -> TreeNode: if not root: return None if num == root.val: return None elif num < root.val: root.left = self.delete(root.left, num) else: root.right = self.delete(root.right, num) return root
def sorted_array_to_bst(self, nums, start, stop): if start <= stop: # 这里 + 1 保证如果对称的时候,取偏右,因为题目中数组是中序遍历的 mid = start + (stop - start + 1) // 2 node = TreeNode(nums[mid]) node.left = self.sorted_array_to_bst(nums, start, mid - 1) node.right = self.sorted_array_to_bst(nums, mid + 1, stop) return node else: return None
def build_bst(start: int, end: int) -> Optional[TreeNode]: nonlocal head if start > end: return None middle = (start + end) // 2 left = build_bst(start, middle - 1) root = TreeNode(head.val) root.left = left head = head.next root.right = build_bst(middle + 1, end) return root
def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode: if not root: return TreeNode(val) if val > root.val: root.right = self.insertIntoBST(root.right, val) if val < root.val: root.left = self.insertIntoBST(root.left, val) return root
def __buildTree(self, preorder_itr, inorder): if not inorder: return None try: curpre = next(preorder_itr) except StopIteration: return None idx = inorder.index(curpre) root = TreeNode(curpre) root.left = self.__buildTree(preorder_itr, inorder[:idx]) root.right = self.__buildTree(preorder_itr, inorder[idx + 1:]) return root
def insertIntoBST11(self, root: TreeNode, val: int) -> TreeNode: self.bianli(root) i = 0 for i in range(len(self.xl)): if val > self.xl[i].val: break if not self.xl[i].right: self.xl[i].right = TreeNode(val) return root if not self.xl[i + 1].left: self.xl[i + 1].left = TreeNode(val) return root
def buildTree(self, preorder, inorder): m = len(preorder) n = len(inorder) if m != n: return None if m == 0: return None val = preorder[0] for i, v in enumerate(inorder): if v == val: break head = TreeNode(val) head.left = self.buildTree(preorder[1:i+1], inorder[0:i]) head.right = self.buildTree(preorder[i+1:], inorder[i+1:]) return head
def helper(in_order: List[int], post_order: List[int]) -> Optional[TreeNode]: if in_order and post_order: root_val = post_order[-1] for root_offset, val in enumerate(in_order): if val == root_val: break else: root_offset = 0 root = TreeNode(root_val) root.left = helper(in_order[:root_offset], post_order[:root_offset]) root.right = helper(in_order[root_offset + 1:], post_order[root_offset:-1]) return root
def buildTree(self, inorder, postorder): m = len(inorder) n = len(postorder) if m != n: return None if m == 0: return None val = postorder[-1] for i, v in enumerate(inorder): if v == val: break head = TreeNode(val) head.left = self.buildTree(inorder[0:i], postorder[0:i]) head.right = self.buildTree(inorder[i+1:], postorder[i:-1]) return head
def sortedArrayToBST(self, nums: List[int]) -> TreeNode: """ 分析了一下,除了 root 可能有 right 其余的都是 left 0 算法不正确,原因在于题目要求的树是 DFS [-10,-3,0,5,9] 5 是 9 的下一层,如果右侧按顺序,就成了 5 在 9 的上一层 1 分析发现,既然是 DF,相当于两树合并起来 还是不对,理解错题目了,是要求平衡二叉树 2 感觉可以用索引来完成 分析时间复杂度 取切片时称动元素为基本操作 1/2 n 1/4 n 1/8 n 1/8 n 1/4 n 1/8 n 1/8 n 1/2 n ... 可以看到每一轮共有 k 个 1/k n 所以每一轮为 n 而轮数为 log(n) 所以 T(n)=O(n logn) 分析空间复杂度 输出的树不考虑,那临时占用的就只有 mid 变量,与结点数一致 S(n)=O(n) """ if not nums: return None mid = len(nums) // 2 root = TreeNode(nums[mid]) # 原数组中序遍历而来,所以左右各能组成树 if 0 < mid: root.left = self.sortedArrayToBST(nums[:mid]) if mid + 1 < len(nums): root.right = self.sortedArrayToBST(nums[mid + 1:]) return root
def is_balanced(root: TreeNode) -> bool: if not root: return True if not (is_balanced(root.left) and is_balanced(root.right)): return False left_height = root.left.val if root.left else 0 right_height = root.right.val if root.right else 0 root.val = max(left_height, right_height) + 1 return -1 <= left_height - right_height <= 1
def sortedArrayToBST(self, nums: List[int]) -> TreeNode: """ 分析了一下,除了 root 可能有 right 其余的都是 left 0 算法不正确,原因在于题目要求的树是 DFS [-10,-3,0,5,9] 5 是 9 的下一层,如果右侧按顺序,就成了 5 在 9 的上一层 1 分析发现,既然是 DF,相当于两树合并起来 还是不对,理解错题目了,是要求平衡二叉树 """ if not nums: return None mid = len(nums) // 2 root = TreeNode(nums[mid]) left = root for i in range(mid - 1, -1, -1): left.left = TreeNode(nums[i]) left = left.left if len(nums) > 2: # 右侧树,从最后一个元倒退回去 root.right = TreeNode(nums[-1]) left = root.right for i in range(len(nums) - 2, mid, -1): left.left = TreeNode(nums[i]) left = left.left return root
def sortedArrayToBST(self, nums: List[int]) -> TreeNode: """ 分析了一下,除了 root 可能有 right 其余的都是 left 0 算法不正确,原因在于题目要求的树是 DF [-10,-3,0,5,9] 5 是 9 的下一层,如果右侧按顺序,就成了 5 在 9 的上一层 """ if not nums: return None mid = len(nums) // 2 root = TreeNode(nums[mid]) left = root for i in range(mid - 1, -1, -1): left.left = TreeNode(nums[i]) left = left.left right = root for i in range(mid + 1, len(nums)): right.right = TreeNode(nums[i]) right = right.right return root
def sortedListToBST(self, head): if not head: return None if not head.next: node = TreeNode(head.val) return node fast = head slow = head prev = None while fast.next and fast.next.next: fast = fast.next.next prev = slow slow = slow.next node = TreeNode(slow.val) right = slow.next if prev: prev.next = None node.left = self.sortedListToBST(head) else: node.left = self.sortedListToBST(None) node.right = self.sortedListToBST(right) return node
def helper(self, ans: dict, pre: TreeNode, nums: List[int]): if not nums: tree = self.copy(pre) node_str = self.node_str(tree) if node_str not in ans: ans[node_str] = tree else: for i, num in enumerate(nums): nums.remove(num) if pre is None: self.helper(ans, TreeNode(num), nums) else: if self.insert(pre, num): # 成功插入才继续 self.helper(ans, pre, nums) self.delete(pre, num) nums.insert(i, num)
def insert_into_bst(root: TreeNode, val: int) -> TreeNode: node, prev, is_left = root, None, False while node: prev = node if val < node.val: node, is_left = node.left, True else: node, is_left = node.right, False new_node = TreeNode(val) if prev is None: return new_node if is_left: prev.left = new_node else: prev.right = new_node return root
def deserialize(data: str) -> Optional[TreeNode]: nodes = map(lambda t: None if t in ("null", "") else TreeNode(int(t)), data.split(",")) root = next(nodes) if root is None: return None queue = deque([root]) is_left = True node = None for next_node in nodes: if next_node: queue.append(next_node) if is_left: node = queue.popleft() node.left = next_node else: node.right = next_node is_left = not is_left return root
def recoverTree(self, root: TreeNode) -> None: """ 前 100 中的最后一题,后续不会再按顺序刷了 可能会解决自己感兴趣的题目,或者是练习某些 tag 从7月1日第一题开始,马上就十一了,连续做了 3 个月的题,保证每天都有一题。 虽然感觉有些难题自己还是思路不太好,但也聊胜于无,加油。 回到这一题 0098 中的一些 trick 应该用不了,还是要老老实实判断当前结点下是否合法,不合法则找出应该和哪一个交换 折腾了一会儿,还是做不出来 >>> root=TreeNode.from_leetcode_array_str('[1,3,null,null,2]') >>> Solution().recoverTree(root) >>> root.to_leetcode_array_str() '[3,1,null,null,2]' """ print(root.to_tree_graph()) bad = self.find_bad(root, float('-inf'), float('inf')) if bad: node = bad[0] replace = self.replace(root, *bad[1:]) node.val, replace.val = replace.val, node.val
def recover_tree(root: TreeNode) -> None: if not root: return prev = TreeNode(-(2 ** 31) - 1) first_error, second_error = None, None def inorder(node: TreeNode) -> None: nonlocal prev, first_error, second_error if node.left: inorder(node.left) if prev.val >= node.val and not first_error: first_error = prev if prev.val >= node.val and first_error: second_error = node prev = node if node.right: inorder(node.right) inorder(root) first_error.val, second_error.val = second_error.val, first_error.val
return levels stack = [root] direction = 1 while stack: level = [] next_stack = [] while stack: node = stack.pop() level.append(node.val) if direction == 1: first = node.left next = node.right else: first = node.right next = node.left if first: next_stack.append(first) if next: next_stack.append(next) direction ^= 1 levels.append(level) stack = next_stack return levels a = [3,9,20,'#','#',15,7] a = [1,2,3,4, '#', '#', 5] tree = TreeNode.from_list(a) s = Solution() print(s.zigzagLevelOrder(tree))
while len(right) < n: right.append('') left = [_fill_width(i, width) for i in left] right = [_fill_width(i, width) for i in right] res = [_fill_width(parent, width * 2 + 4)] for l, r in zip(left, right): res.append(l + ' ' * 4 + r) return res def _max_line_width(lines: List[str]) -> int: if not lines: return 0 return len(max(lines, key=lambda x: len(x))) def _fill_width(line: str, width: int) -> str: n = width - len(line) left = n // 2 right = n - left return ' ' * left + line + ' ' * right if __name__ == '__main__': from leetcode import TreeNode print(to_tree_graph(TreeNode.from_num(123456))) print( to_tree_graph( TreeNode.from_array([3, None, 30, 10, None, None, 15, None, 45])))
def invert(node: TreeNode) -> None: node.left, node.right = node.right, node.left if node.left: invert(node.left) if node.right: invert(node.right)
def test(self): tree = TreeNode.from_iter(range(1, 10)) print(tree) print() morris_inorder_traversal(tree)
# Definition for a binary tree node # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None from leetcode import TreeNode class Solution: # @param root, a tree node # @return a boolean def isValidBST(self, root): return self.validBST(root, None, None) def validBST(self, root, Min, Max): if not root: return True if Min != None and Min >= root.val: return False if Max != None and Max <= root.val: return False return (self.validBST(root.left, Min, root.val) and self.validBST(root.right, root.val, Max)) if __name__ == '__main__': root = TreeNode(0) root.right = TreeNode(-1) s = Solution() print s.isValidBST(root)