def countPairs(self, root: TreeNode, distance: int) -> int: adjust = defaultdict(list) for node in TreeUtil.preOrderTraversalIterator(root): if node.left: adjust[node].append(node.left) adjust[node.left].append(node) if node.right: adjust[node].append(node.right) adjust[node.right].append(node) ans = 0 for bfsRootNode in adjust: if bfsRootNode.left or bfsRootNode.right: continue queue = [(bfsRootNode, 0)] # Node, _distance visited = set() while queue: node, _distance = queue.pop(0) if node in visited or _distance >= distance: continue visited.add(node) for nextNode in filter(lambda node: node not in visited, adjust[node]): if nextNode.left is None and nextNode.right is None: if _distance < distance: # print(bfsRootNode.val, nextNode.val) ans += 1 else: queue.append((nextNode, _distance + 1)) return ans // 2
def getChild2ParentMap(self, root: TreeNode): child2parent = {root: None} for node in TreeUtil.preOrderTraversalIterator(root): if node.left: child2parent[node.left] = node if node.right: child2parent[node.right] = node return child2parent
def goodNodes(self, root: TreeNode) -> int: heap = TreeUtil.toValHeap(root) heap = [None] + heap count = 0 for i in range(1, len(heap)): if heap[i] is not None and self.isGoodNode(heap, i): count += 1 return count
def isValidBST(self, root: TreeNode) -> bool: if not root: return False iterator = TreeUtil.inOrderTraversalIterator(root) previous = next(iterator) for node in iterator: if node.val <= previous.val: return False previous = node return True
def isSymmetric(self, root: TreeNode) -> bool: heap = TreeUtil.toValHeap(root) maxLevel = int(math.log2(len(heap) + 1)) for level in range(1, maxLevel + 1): indexBegin = 2**(level - 1) - 1 indexEnd = 2**level - 1 - 1 while indexBegin < indexEnd: if heap[indexBegin] != heap[indexEnd]: return False indexBegin += 1 indexEnd -= 1 return True
def isSubtree(self, s: TreeNode, t: TreeNode) -> bool: if t is None: return s is None for subRootS in TreeUtil.postOrderTraversalIterator(s): if subRootS.val != t.val or TreeUtil.maxLevel( subRootS) != TreeUtil.maxLevel(t): continue if TreeUtil.preOrderTraversal(subRootS) == TreeUtil.preOrderTraversal(t) \ and TreeUtil.inOrderTraversal(subRootS) == TreeUtil.inOrderTraversal(t): return True return False
def longestConsecutive_clumsy(self, root: TreeNode) -> int: def detectLongestPath(root: TreeNode, valIs: int) -> int: if not root or root.val != valIs: return 0 leftLongestPathLength = detectLongestPath(root.left, valIs + 1) rightLongestPathLength = detectLongestPath(root.right, valIs + 1) if leftLongestPathLength > rightLongestPathLength: return 1 + leftLongestPathLength else: return 1 + rightLongestPathLength longest = 0 for node in TreeUtil.inOrderTraversalIterator(root): longestLocal = detectLongestPath(node, node.val) if longestLocal > longest: longest = longestLocal return longest
def maxDepth(self, root: TreeNode) -> int: return TreeUtil.maxLevel(root)
import threading from test_script import TreeNode, TreeUtil, timer class Codec: def serialize(self, root: TreeNode) -> str: """ Encodes a tree to a single string. """ return str(TreeUtil.toValHeapToDict(root)).replace(' ', '') @timer def deserialize(self, data: str) -> TreeNode: """ Decodes your encoded data to tree. """ return TreeUtil.createTreeByHeapExpressedByDict(eval(data)) root = TreeUtil.createTreeByPreInOrder(list(range(1, 1001)), list(range(1, 1001))) treeDictStr = Codec().serialize(root) Codec().deserialize(treeDictStr) print(treeDictStr)
from test_script import TreeNode from test_script import TreeUtil class Solution: def isValidBST(self, root: TreeNode) -> bool: if not root: return False iterator = TreeUtil.inOrderTraversalIterator(root) previous = next(iterator) for node in iterator: if node.val <= previous.val: return False previous = node return True print(Solution().isValidBST( TreeUtil.createBinaryTree([10, 5, 15, None, None, 6, 20])))
def deserialize(self, data: str) -> TreeNode: """ Decodes your encoded data to tree. """ return TreeUtil.createTreeByHeapExpressedByDict(eval(data))
from test_script import TreeNode, TreeUtil class Solution: def isSubtree(self, s: TreeNode, t: TreeNode) -> bool: if t is None: return s is None for subRootS in TreeUtil.postOrderTraversalIterator(s): if subRootS.val != t.val or TreeUtil.maxLevel( subRootS) != TreeUtil.maxLevel(t): continue if TreeUtil.preOrderTraversal(subRootS) == TreeUtil.preOrderTraversal(t) \ and TreeUtil.inOrderTraversal(subRootS) == TreeUtil.inOrderTraversal(t): return True return False print(Solution().isSubtree(TreeUtil.createBinaryTree([1, 2, 3]), TreeUtil.createBinaryTree([2, 3])))
class Solution: def isGoodNode(self, heap: List[object], index: int) -> bool: """ 使用heap判断第index个节点是否为好节点 :param heap: 保存节点内容的堆(1-based index) :param index: 第index个节点(1-based index) :return: """ nowNumber = heap[index] while index > 0: if heap[index] > nowNumber: return False index //= 2 # 找父亲节点 return True def goodNodes(self, root: TreeNode) -> int: heap = TreeUtil.toValHeap(root) heap = [None] + heap count = 0 for i in range(1, len(heap)): if heap[i] is not None and self.isGoodNode(heap, i): count += 1 return count tree = TreeUtil.createBinaryTree( [-5, -1, -4, None, None, -5, 0, None, None, None, None, -5, None, -1, 2]) tree.right.right.left.right = TreeUtil.createBinaryTree( [-3, None, -5, None, None, None, -4]) print(Solution().goodNodes(tree))
def serialize(self, root: TreeNode) -> str: """ Encodes a tree to a single string. """ return str(TreeUtil.toValHeapToDict(root)).replace(' ', '')
indexBegin += 1 indexEnd -= 1 return True def isSymmetric_fast(self, root: TreeNode) -> bool: def equals(node1: TreeNode, node2: TreeNode): if not node1 and not node2: return True elif (node1 and node2) is None: return False return node1.val == node2.val and equals( node1.left, node2.right) and equals(node1.right, node2.left) if not root: return True return equals(root.left, root.right) speedtest([Solution().isSymmetric, Solution().isSymmetric_fast], [ TreeUtil.createTreeByPreInOrder( [1, 2, 4, 6, 5, 7, 9, 10, 8, 3, 5, 8, 7, 9, 10, 4, 6], [4, 6, 2, 7, 10, 9, 5, 8, 1, 8, 5, 9, 10, 7, 3, 6, 4]) ]) speedtest([Solution().isSymmetric, Solution().isSymmetric_fast], [ TreeUtil.createTreeByPreInOrder( [1, 2, 4, 6, 5, 7, 9, 10, 8, 2, 5, 8, 7, 9, 10, 4, 6], [4, 6, 2, 7, 10, 9, 5, 8, 1, 8, 5, 9, 10, 7, 2, 6, 4]) ])
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: def contain(root: TreeNode, findNode: TreeNode): return TreeUtil.findNodeByVal(root, findNode.val) def getCommonAncestor(node: TreeNode): if node is p: if contain(node, q): return node return None elif node is q: if contain(node, p): return node return None if contain(node.left, p): if contain(node.right, q): return node return getCommonAncestor(node.left) elif contain(node.left, q): if contain(node.right, p): return node return getCommonAncestor(node.right) return getCommonAncestor(root) # root = TreeUtil.createBinaryTree([3, 5, 1, 6, 2, 0, 8, None, None, 7, 4]) root = TreeUtil.createBinaryTree([3, 5, 1, 6, 2, 0, 8, None, None, 7, 4]) print(Solution().lowestCommonAncestor(root, TreeUtil.findNodeByVal(root, 5), TreeUtil.findNodeByVal(root, 4)).val)
valIs = root.val else: nowLength += 1 longest = max(longest, nowLength) detectLongestPath(root.left, valIs + 1, nowLength) detectLongestPath(root.right, valIs + 1, nowLength) longest = 0 if not root: return 0 detectLongestPath(root, root.val, 0) return longest speedtest( [Solution().longestConsecutive, Solution().longestConsecutive_clumsy], [TreeUtil.createTreeByPreInOrder([1, 3, 2, 4, 5], [1, 2, 3, 4, 5])]) speedtest( [Solution().longestConsecutive, Solution().longestConsecutive_clumsy], [TreeUtil.createTreeByPreInOrder([2, 3, 2, 1], [2, 1, 2, 3])]) root = TreeNode(1) node = root for i in range(2, 5001): node.right = TreeNode(i) node = node.right speedtest( [Solution().longestConsecutive, Solution().longestConsecutive_clumsy], [root])
def contain(root: TreeNode, findNode: TreeNode): return TreeUtil.findNodeByVal(root, findNode.val)
def levelOrder(self, root: TreeNode) -> List[List[int]]: return TreeUtil.breadthFirstTraversal(root)
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode: return TreeUtil.createTreeByPreInOrder(preorder, inorder)
for node in TreeUtil.preOrderTraversalIterator(root): if node.left: adjust[node].append(node.left) adjust[node.left].append(node) if node.right: adjust[node].append(node.right) adjust[node.right].append(node) ans = 0 for bfsRootNode in adjust: if bfsRootNode.left or bfsRootNode.right: continue queue = [(bfsRootNode, 0)] # Node, _distance visited = set() while queue: node, _distance = queue.pop(0) if node in visited or _distance >= distance: continue visited.add(node) for nextNode in filter(lambda node: node not in visited, adjust[node]): if nextNode.left is None and nextNode.right is None: if _distance < distance: # print(bfsRootNode.val, nextNode.val) ans += 1 else: queue.append((nextNode, _distance + 1)) return ans // 2 print(Solution().countPairs(TreeUtil.createTreeByHeap([1, 2, 3, None, 4, None, None]), 3)) print(Solution().countPairs(TreeUtil.createTreeByHeap([1, 2, 3, 4, 5, 6, 7]), 3))