树的定义
1 | class TreeNode: |
144. Binary Tree Preorder Traversal
二叉树前序遍历
1 | Input: [1,null,2,3] |
方法一:iteratively
1 | def preorderTraversal(self, root: 'TreeNode') -> 'List[int]': |
方法二:recursively
1 | def preorder_traversal(root): |
589. N-ary Tree Preorder Traversal
N-叉树的前序遍历。N叉树和二叉树有个区别,就是N叉树不需要考虑子节点知否为空,做单独的判断。原题
方法一:recursively.
1 | def preorder(self, root): |
方法二:iteratively.
1 | def preorder(self, root): |
94. Binary Tree Inorder Traversal
中序遍历二叉树
1 | Input: [1,null,2,3] |
方法一:使用栈迭代。
1 | def inorderTraversal(self, root: TreeNode) -> List[int]: |
1 | def inorderTraversal(self, root: TreeNode) -> List[int]: |
145. Binary Tree Postorder Traversal
后序遍历二叉树
1 | Input: [1,null,2,3] |
方法一:根右左,再倒序。
1 | def postorder_traversal(root): |
方法二:思想: 使用last
作为判断是否该节点的右子树完成遍历,如果一个node.right
已经刚刚遍历完毕,那么将last==node.right
,否则将会寻找node.right
。
1 | def postorderTraversal(self, root): |
方法三:使用boolean判断一个节点是否被遍历过
1 | def postorderTraversal(self, root): |
方法四:dfs.
1 | def postorderTraversal(self, root: 'TreeNode') -> 'List[int]': |
590. N-ary Tree Postorder Traversal
N-叉树的后序遍历。原题
方法一:recursively.
1 | def postorder(self, root): |
方法二:iteratively and reversed.
1 | def postorder(self, root): |
方法三:iteratively and flag.
1 | def postorder(self, root): |
100. Same Tree
判断相同的二叉树。原题
1 | Input: 1 1 |
方法一:recursively
1 | def isSameTree(self, p: 'TreeNode', q: 'TreeNode') -> 'bool': |
方法二:recursively, tuple
1 | def is_same_tree(p, q): |
方法三:iteratively.
1 | def isSameTree(self, p: 'TreeNode', q: 'TreeNode') -> 'bool': |
101. Symmetric Tree
判断二叉树是否对称。原题
1 | 1 |
方法一:recursively.
1 | def isSymmetric(self, root: 'TreeNode') -> 'bool': |
方法二:iteratively.
1 | def isSymmetric(self, root: 'TreeNode') -> 'bool': |
104. Maximum Depth of Binary Tree
二叉树最大深度。原题
1 | 3 |
方法一:recursively
1 | def max_depth(root): |
方法二:iteratively. BFS with deque
1 | def maxDepth(self, root: 'TreeNode') -> 'int': |
可以参考102分层遍历写法,最后求长度。
559. Maximum Depth of N-ary Tree
N-叉树的最大深度。原题
方法一:BFS with deque.同上题一样。
1 | def maxDepth(self, root: 'Node') -> 'int': |
1 | def maxDepth(self, root): |
1 | def maxDepth(self, root: 'Node') -> 'int': |
111. Minimum Depth of Binary Tree
求根节点到叶子节点的最小深度。原题
方法一:recursively
1 | def minDepth(self, root): |
1 | def minDepth(self, root: 'TreeNode') -> 'int': |
方法三:迭代法,BFS
1 | def minDepth(self, root: 'TreeNode') -> 'int': |
105. Construct Binary Tree from Preorder and Inorder Traversal
根据前序遍历和中序遍历重建二叉树。原题
1 | preorder = [3,9,20,15,7] |
方法一:切片。
1 | def buildTree(preorder, inorder): |
reverse
是为了增加效率。
1 | def buildTree(self, preorder: 'List[int]', inorder: 'List[int]') -> 'TreeNode': |
106. Construct Binary Tree from Inorder and Postorder Traversal
根据中序遍历和后序遍历重建二叉树。原题
方法一:切片、
1 | def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode: |
1 | def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode: |
1 | def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode: |
889. Construct Binary Tree from Preorder and Postorder Traversal
根据前序和后序重建二叉树。原题
1 | Input: pre = [1,2,4,5,3,6,7], post = [4,5,2,6,7,3,1] |
方法一:index的方式、、
1 | def constructFromPrePost(self, pre: List[int], post: List[int]) -> TreeNode: |
1 | class Solution: |
572. Subtree of Another Tree
判断是否是树的子结构。原题
思路:这道题是遍历加判断相同树的结合。这里采用前序遍历和递归判断相同树。
1 | def isSubtree(self, s: 'TreeNode', t: 'TreeNode') -> 'bool': |
方法二:生成器写法。
1 |
102. Binary Tree Level Order Traversal
分层遍历二叉树。原题
注意:循环条件要加上root,以防止root is None
1 | def levelOrder(self, root: 'TreeNode') -> 'List[List[int]]': |
103. Binary Tree Zigzag Level Order Traversal
之字形打印二叉树。原题
1 | def zigzagLevelOrder(self, root: 'TreeNode') -> 'List[List[int]]': |
107. Binary Tree Level Order Traversal II
和102题不同的是,从下到上分层打印。原题
方法一:将结果倒序输出。1 | def levelOrderBottom(self, root): |
方法二:也可以从前面插入元素。
1 | def levelOrderBottom(self, root): |
429. N-ary Tree Level Order Traversal
分层打印N叉树。原题
1 | def levelOrder(self, root: 'Node') -> 'List[List[int]]': |
637. Average of Levels in Binary Tree
遍历一个二叉树,求每层节点的平均值,按照节点不为空的个数。原题
1 | Input: |
1 | def averageOfLevels(self, root: 'TreeNode') -> 'List[float]': |
515. Find Largest Value in Each Tree Row
找到树每层的最大值。原题
方法一:BFS. 此解法秒。
1 | def largestValues(self, root: TreeNode) -> List[int]: |
987. Vertical Order Traversal of a Binary Tree
垂直遍历二叉树,从左到右,从上到下,如果节点具有相同位置,按照值从小到大。原题
1 | Input: [1,2,3,4,5,6,7] |
方法一:dfs. 通过建立一个字典数组,将对应的节点使用深度优先遍历初始化数组。然后按照x, y, val三个优先级进行排序。
1 | def verticalTraversal(self, root: 'TreeNode') -> 'List[List[int]]': |
257. Binary Tree Paths
打印二叉树从根节点到叶子节点全部路径。原题
1 | Input: |
iteratively。思路:采用前序遍历二叉树,使用tuple保存节点当前路径,如果是叶子节点,则添加到结果中。开始老是想着用'->'.join()
,这样反而麻烦,直接使用字符串保存就好。
1 | def binaryTreePaths(self, root: 'TreeNode') -> 'List[str]': |
1 | def binaryTreePaths(self, root: 'TreeNode') -> 'List[str]': |
StefanPochmann
大神的方法。最开始想到一半,中间那层循环想到了,但没想到用递归。
1 | def binaryTreePaths(self, root): |
988. Smallest String Starting From Leaf
求字典顺序最小的路径,路径指叶子节点到根节点的路径。0对应a,1对应b。原题
1 | Input: [0,1,2,3,4,3,4] |
方法一:先列出所有根到叶子的路径,再reverse求最小值。
1 | def smallestFromLeaf(self, root: 'TreeNode') -> 'str': |
1 | def smallestFromLeaf(self, root: 'TreeNode') -> 'str': |
112. Path Sum
判断是否具有从根节点到叶子节点上的值和为sum。原题
方法一:recursively
1 | def hasPathSum(self, root: 'TreeNode', total: 'int') -> 'bool': |
方法二:iteratively
1 | def hasPathSum(self, root: 'TreeNode', total: 'int') -> 'bool': |
113. Path Sum II
上题的升级版,要求二维数组返回所有路径。原题
1 | sum = 22 |
1 | [ |
1 | def pathSum(self, root: 'TreeNode', total: 'int') -> 'List[List[int]]': |
recursively. 先找出所有路径,再过滤,实际上和257题一样。不过这并没有把这道题的特性涵盖进去。
1 | def pathSum(self, root, sum_val): |
1 | def pathSum(self, root, sum): |
1 | def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]: |
297. Serialize and Deserialize Binary Tree
序列化反序列化二叉树。原题
1 | class Codec: |
110. Balanced Binary Tree
判断是否是平衡二叉树。原题
方法一:递归+递归。
1 | def isBalanced(self, root): |
方法二:上诉两种方法中都包含了一些无意义的重复遍历。这里采用后序遍历,边遍历边判断,不会重复节点。受此思想启发,添加一种后序遍历二叉树的方法。
1 | def isBalanced(self, root): |
[1,2,2,3,3,null,null,4,4]
会错误的返回True
而不是False
。
1 | def isBalanced(self, root: TreeNode) -> bool: |
108. Convert Sorted Array to Binary Search Tree
将有序数组转换成二叉搜索树。原题
1 | Given the sorted array: [-10,-3,0,5,9], |
方法一:答案不唯一,居然一次就通过了。递归的思想还是简单一些的。
1 | def sortedArrayToBST(self, nums): |
1 | def sortedArrayToBST(self, nums: 'List[int]') -> 'TreeNode': |
235. Lowest Common Ancestor of a Binary Search Tree
寻找二叉搜索树的最小公共祖先。原题
方法一:iteratively.1 | def lowestCommonAncestor(self, root, p, q): |
方法二:recursively.
1 | def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': |
404. Sum of Left Leaves
求一个二叉树所有左叶子节点的和。原题
方法一:iteratively.这里使用了tuple记录是否为左叶子节点。1 | def sumOfLeftLeaves(self, root: 'TreeNode') -> 'int': |
方法二:recursively.
1 | def sumOfLeftLeaves(self, root: 'TreeNode') -> 'int': |
938. Range Sum of BST
给两个节点的值,求二叉搜索树在这两个值之间的节点和。每个节点的值唯一。原题
1 | Input: root = [10,5,15,3,7,null,18], L = 7, R = 15 |
方法一:因为是竞赛题,所以没追求效率,所以这里先前序遍历了一下,再根据条件求和。
1 | def rangeSumBST(self, root, L, R): |
1 | def rangeSumBST(self, root: 'TreeNode', L: 'int', R: 'int') -> 'int': |
1 | def rangeSumBST(self, root: TreeNode, low: int, high: int) -> int: |
530. Minimum Absolute Difference in BST
求二叉搜索树任意两个节点的最小差。原题
1 | Input: |
1 | def getMinimumDifference(self, root: 'TreeNode') -> 'int': |
783. Minimum Distance Between BST Nodes
二叉搜索树两个节点的最小值。和530是一道题。原题
1 | Input: root = [4,2,6,1,3,null,null] |
方法一:递归 + 生成器, 遍历了两次。
1 | def minDiffInBST(self, root: 'TreeNode') -> 'int': |
1 | def minDiffInBST(self, root: TreeNode) -> int: |
1 | class Solution: |
538. Convert BST to Greater Tree
二叉搜索树转换。使得节点的值等于所有比它大的节点的和。原题
1 | Input: The root of a Binary Search Tree like this: |
1 | def convertBST(self, root: TreeNode) -> TreeNode: |
1 | def convertBST(self, root: TreeNode) -> TreeNode: |
1 | def convertBST(self, root: TreeNode) -> TreeNode: |
958. Check Completeness of a Binary Tree
判断二叉树是否是完整二叉树。完整二叉树为:除了最后一层所有节点不能为空,最后一层节点全部去靠左。原题
Example 1:
1 | Input: [1,2,3,4,5,6] |
Example 2:
1 | Input: [1,2,3,4,5,null,7] |
方法一:采用分层遍历的方式,判断每层的节点是否是2**level。最后一层采用切片的方式判断最左原则。
1 | class Solution: |
1 | def isCompleteTree(self, root: 'TreeNode') -> 'bool': |
543. Diameter of Binary Tree
求二叉树的最大直径,即任意两节点的长度。原题
1 | 1 |
方法一: recursively, 使用一个实例变量计算了最大值。
1 | def diameterOfBinaryTree(self, root: 'TreeNode') -> 'int': |
965. Univalued Binary Tree
判断一个二叉树是否所有节点具有相同的值。原题
方法一:recursively。1 | def isUnivalTree(self, root: 'TreeNode') -> 'bool': |
方法二:iteratively.常规写法。
1 | def isUnivalTree(self, root: 'TreeNode') -> 'bool': |
方法二:前序遍历,生成器方法。
1 | def isUnivalTree(self, root: 'TreeNode') -> 'bool': |
563. Binary Tree Tilt
返回一个二叉树整个树的倾斜度。所有节点倾斜度的总和。节点的倾斜度等于左子树和右子树所有和差的绝对值。原题
1 | Input: |
方法一:recursively. 这里用tuple记录了节点总和和倾斜度总和。
1 | def findTilt(self, root): |
1 | def findTilt(self, root: 'TreeNode') -> 'int': |
606. Construct String from Binary Tree
根据二叉树重建字符串,使用()
表示嵌套关系。原题
1 | Input: Binary tree: [1,2,3,4] |
方法一:recursively. 左右节点有一点区别,在于如果左节点为空,右节点不为空,要保留左节点的括号。
1 | def tree2str(self, t): |
617. Merge Two Binary Trees
合并两个二叉树,相同位置的节点值相加,空节点算0.原题
方法一:recursively.1 | def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode: |
方法二:iteratively.
1 | def mergeTrees(self, t1, t2): |
653. Two Sum IV - Input is a BST
判断二叉树中是否有两个节点相加为k。原题
1 | Input: |
方法一:preorder + set.
1 | def findTarget(self, root, k): |
669. Trim a Binary Search Tree
根据范围修剪二叉搜索树,注意是二叉搜索树,不是普通的二叉树。原题
1 | Input: |
方法一:recursively.
1 | def trimBST(self, root, L, R): |
671. Second Minimum Node In a Binary Tree
找出二叉树中第二小的节点值。左右子节点同时存在或同时不存在,根节点小于等于任意子节点。原题
1 | Input: |
方法一:先放到set里.
1 | def findSecondMinimumValue(self, root: 'TreeNode') -> 'int': |
1 | def findSecondMinimumValue(self, root): |
方法三:还没想出来,以上两种都没有利用到一些题中已知条件,我看Solution中给出的及一些Discuss中的答案也忽略了这个条件。想了想无论是哪个顺序遍历,或者深度广度优先,都没能很好的利用这个条件。
687. Longest Univalue Path
相同节点最长路径,路径长度按照两个节点之间的边距,也就是节点数-1。原题
1 | 5 |
1 | def longestUnivaluePath(self, root): |
700. Search in a Binary Search Tree
在二叉搜索树中搜索节点。原题
1 | Given the tree: |
方法一:recursively.
1 | def searchBST(self, root: 'TreeNode', val: 'int') -> 'TreeNode': |
方法二:iteratively.
1 | def searchBST(self, root: 'TreeNode', val: 'int') -> 'TreeNode': |
872. Leaf-Similar Trees
叶子相近的树,只从左到右遍历叶子节点的顺序相同的两棵树。原题
方法一:前序遍历+生成器。空间复杂度过高,beats 1%。
1 | def leafSimilar(self, root1: 'TreeNode', root2: 'TreeNode') -> 'bool': |
1 | def leafSimilar(self, root1: 'TreeNode', root2: 'TreeNode') -> 'bool': |
897. Increasing Order Search Tree
根据中序遍历建立一个只有右子树的二叉树。要求在原树上修改。原题
1 | Example 1: |
方法一:iteratively.
1 | def increasingBST(self, root: TreeNode) -> TreeNode: |
方法二:生成器。
1 | def increasingBST(self, root: 'TreeNode') -> 'TreeNode': |
1 | def increasingBST(self, root: 'TreeNode', tail=None) -> 'TreeNode': |
993. Cousins in Binary Tree
表弟节点指两个节点在同一深度,并且父节点不同。判断两个节点是否是表弟节点。树中节点值唯一。原题
方法一:用dict记录。
1 | def isCousins(self, root: 'TreeNode', x: 'int', y: 'int') -> 'bool': |
230. Kth Smallest Element in a BST
二叉搜索树的第K小节点值。原题
1 | Input: root = [3,1,4,null,2], k = 1 |
方法一:生成器前序遍历。
1 | def kthSmallest(self, root: TreeNode, k: int) -> int: |
方法二:迭代。
1 | def kthSmallest(self, root: TreeNode, k: int) -> int: |
98. Validate Binary Search Tree
验证一个树是否是二叉搜索树。原题
1 | 5 |
方法一:中序遍历即可。
1 | def isValidBST(self, root: TreeNode) -> bool: |
方法二:整个活。
1 | def isValidBST(self, root: TreeNode) -> bool: |
109. Convert Sorted List to Binary Search Tree
将有序链表转成平衡二叉搜索树。原题
1 | Given the sorted linked list: [-10,-3,0,5,9], |
方法一:先遍历链表,再二分递归创建树。
1 | def sortedListToBST(self, head: ListNode) -> TreeNode: |
head
可变对象。
1 | def sortedListToBST(self, head: ListNode) -> TreeNode: |
1008. Construct Binary Search Tree from Preorder Traversal
根据前序遍历重建二叉搜索树。原题
1 | Input: [8,5,1,7,10,12] |
方法一:recursively.
1 | def bstFromPreorder(self, preorder: List[int]) -> TreeNode: |
236. Lowest Common Ancestor of a Binary Tree
二叉树两个节点的最小公共祖先。原题
方法一: 递归,是用mid表示当前节点是否是其中的一个。
1 | def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': |
1 | def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': |
list(path)
,否则由于可变对象的问题,会导致最后结果为[]
。
1 | def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': |
654. Maximum Binary Tree
根据数组建立一个树,要求根节点为数组最大的树。原题
方法一:此题秒,不过感觉还有更优解,查了一圈没找到。
1 | def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode: |
513. Find Bottom Left Tree Value
寻找二叉树最底层的最左节点。原题
方法一:根据分层遍历改编。
1 | def findBottomLeftValue(self, root: TreeNode) -> int: |
方法二:双端队列,BFS.
1 | def findBottomLeftValue(self, root: TreeNode) -> int: |
方法三:循环时改变迭代对象,这种方式个人觉得不好。不过好在是在遍历之前添加到末端。
1 | def findBottomLeftValue(self, root: TreeNode) -> int: |
814. Binary Tree Pruning
剪掉树中不包含1的子树。原题
方法一:递归。
1 | def pruneTree(self, root: TreeNode) -> TreeNode: |
199. Binary Tree Right Side View
二叉树从右向左看时,从上到下的节点。原题
方法一:和分层遍历思想相同。
1 | def rightSideView(self, root: TreeNode) -> List[int]: |
方法二:dfs. 从右到左深度遍历,用一个深度变量控制是否是第一个最右节点。
1 | def rightSideView(self, root: TreeNode) -> List[int]: |
662. Maximum Width of Binary Tree
二叉树的最大宽度。原题
方法一:常规队列写法。需要注意的是,每层遍历要用最右边的减去最左边的才是宽度。
1 | def widthOfBinaryTree(self, root: TreeNode) -> int: |
enumerate其实就是计算2*pos, 2*pos+1
。
1 | def widthOfBinaryTree(self, root: TreeNode) -> int: |
222. Count Complete Tree Nodes
统计完整树的节点个数。原题
方法一:二分法。比较左子树的深度和右子树的深度,如果相同则表明左子树为满树,右子树为完整树。如果不同则表明左子树为完整树,右子树为满树。
1 | def countNodes(self, root: TreeNode) -> int: |
1022. Sum of Root To Leaf Binary Numbers
计算所有根到叶子节点路径二进制数表示的的和。原题
1 | Input: [1,0,1,0,1,0,1] |
思路和 257.Binary Tree Paths一样。
1 | def sumRootToLeaf(self, root: TreeNode) -> int: |
1026. Maximum Difference Between Node and Ancestor
祖先和其子节点的最大差绝对值。原题
方法一:周赛时写的dfs. 380ms. 瓶颈在于每次都求一次最大值和最小值。
1 | def maxAncestorDiff(self, root: TreeNode) -> int: |
1 | def maxAncestorDiff(self, root: TreeNode) -> int: |
1038. Binary Search Tree to Greater Sum Tree
二叉搜索树转成一颗规则的树,从右根左的顺序累加节点值。原题
方法一:使用栈。
1 | def bstToGst(self, root: TreeNode) -> TreeNode: |
方法二:Lee神的递归方式。
1 | class Solution: |
1080. Insufficient Nodes in Root to Leaf Paths
计算所有的根到叶子节点的路径,如果路径和小于给定值,则剪掉这个树枝。原题
方法一:递归。
1 | def sufficientSubset(self, root: TreeNode, limit: int) -> TreeNode: |
1161. Maximum Level Sum of a Binary Tree
求最节点和最大层的层数。原题
方法一:分层遍历
1 | def maxLevelSum(self, root: TreeNode) -> int: |
1104. Path In Zigzag Labelled Binary Tree
之字形树的目标节点路径。原题
方法一:迭代,此题纯粹是数学题,这里先假设非之字形的树,找到规律,然后知道每层的节点数再相减。
1 | def pathInZigZagTree(self, label: int) -> List[int]: |
方法二:Lee神的递归。原理一样,层数n是通过查2的幂求的。
1 | def pathInZigZagTree(self, x): |
1110. Delete Nodes And Return Forest
给定一个树,删除指定的一些节点,然后删除的节点的左右子树成为单独的根节点。返回所有的树。原题
1 | Input: root = [1,2,3,4,5,6,7], to_delete = [3,5] |
方法一:递归。做着题的时候有个误区:在当前节点被删除后,找到其在父节点对应的位置,然后置为空。实际上应该讲根节点删除的状态保留,在下一层处理。
1 | def delNodes(self, root: TreeNode, to_delete: List[int]) -> List[TreeNode]: |
1123. Lowest Common Ancestor of Deepest Leaves
最深的叶子节点的最小公共祖先。原题
1 | Input: root = [1,2,3] |
方法一:Lee神的方法比我的好太多,我借鉴了之前的dfs的方式遍历所有的path,然后再清洗比较。其实直接递归即可。
1 | def lcaDeepestLeaves(self, root: TreeNode) -> TreeNode: |
1382. Balance a Binary Search Tree
将一个二叉搜索树转为平衡二叉搜索树。原题
方法一:想到二叉搜索树首先想到中序遍历,所以一共分为2步,一步是遍历出所有节点,再根据节点重建一个平衡的二叉搜索树。
1 | class Solution: |
1372. Longest ZigZag Path in a Binary Tree
二叉树中最长的z字形路径。原题
方法一:用了不少变量来控制走位。
1 | def longestZigZag(self, root: TreeNode) -> int: |
方法二:-1的妙用。
1 | def longestZigZag(self, root: TreeNode) -> int: |
1367. Linked List in Binary Tree
判断一个链表是否在二叉树的路径中。原题
方法一:递归。
1 | def isSubPath(self, head: ListNode, root: TreeNode) -> bool: |
124. Binary Tree Maximum Path Sum
二叉树的最大路径和,可以不经过根节点。原题
1 | Input: [-10,9,20,null,null,15,7] |
方法一:递归。开始有一点没想明白,对于任意节点来说,都有左右两条path, 包括根节点。
1 | def maxPathSum(self, root: TreeNode) -> int: |
1443. Minimum Time to Collect All Apples in a Tree
收集苹果的最小路径。原题
1 | Input: n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,true,true,false] |
方法一:每个苹果的路径都是节点到根的两倍距离。
1 | def minTime(self, n: int, edges: List[List[int]], hasApple: List[bool]) -> int: |
1339. Maximum Product of Splitted Binary Tree
将一个树砍成两颗树,使两个节点和乘积最大。原题
方法一:需要遍历2次,一次求出所有节点和。
1 | def maxProduct(self, root: TreeNode) -> int: |
1315. Sum of Nodes with Even-Valued Grandparent
祖父节点为偶数的节点和。原题
1 | def sumEvenGrandparent(self, root: TreeNode, p=1, gp=1) -> int: |
1457. Pseudo-Palindromic Paths in a Binary Tree
伪回文路径的个数。指排列能够成为回文的路径。原题
1 | Input: root = [2,3,1,3,1,null,1] |
方法一:竞赛时的答案。
1 | def pseudoPalindromicPaths (self, root: TreeNode) -> int: |
1 | def pseudoPalindromicPaths (self, root: TreeNode) -> int: |
129. Sum Root to Leaf Numbers
根到叶子节点组成的数字和。原题
1 | Input: [1,2,3] |
方法一:dfs 写法上迟疑了一下,还是要判断是否为根节点的,避免和累加了2次。
1 | def sumNumbers(self, root: TreeNode) -> int: |
114. Flatten Binary Tree to Linked List
将一个二叉树变成一个链表,要求在原节点上操作。原题
1 | 1 |
方法一:变成左子树操作直观一点,所以先将它变成左子树,然后再镜像。
1 | def flatten(self, root: TreeNode) -> None: |
方法二:先把俩节点左右互换。
1 | def flatten(self, root: TreeNode) -> None: |
1 | def countPairs(self, root: TreeNode, distance: int) -> int: |
1 | def countPairs(self, root: TreeNode, distance: int) -> int: |
450. Delete Node in a BST
删除二叉搜索树的一个节点。原题
方法一:递归,好久没做二叉树有点生疏,想了半天。
1 | def deleteNode(self, root: TreeNode, key: int) -> TreeNode: |
971. Flip Binary Tree To Match Preorder Traversal
给你一个二叉树和一个前序遍历,判断二叉树否通过互换左右子树来达到前序遍历的顺序,返回这样的节点编号,没有则返回-1。原题
1 | Input: root = [1,2], voyage = [2,1] |
方法一:递归。第一次ac的方法。
1 | def flipMatchVoyage(self, root: TreeNode, v: List[int]) -> List[int]: |
1 | def flipMatchVoyage(self, root: TreeNode, v: List[int]) -> List[int]: |
951. Flip Equivalent Binary Trees
和971差不多,比较的是两棵树。原题
方法一:第一次提交时少考虑了一个case就是左右节点都相同。这种情况下可翻转也可不翻转。然后想or的关系,担心会超时。好在树的节点并没有很多。而且用时也不高beats了90%。
1 | def flipEquiv(self, root1: TreeNode, root2: TreeNode) -> bool: |
方法二:理论上来说是方法一快,但是可以忽略不计。
1 | def flipEquiv(self, root1: TreeNode, root2: TreeNode) -> bool: |
863. All Nodes Distance K in Binary Tree
找出树中距离目标节点为K的节点值。原题
1 | Input: root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, K = 2 |
方法一:这个方法想了一下,没敢往下细想。先把他变成那种无向图。然后bfs。
1 | def distanceK(self, root: TreeNode, target: TreeNode, K: int) -> List[int]: |
865. Smallest Subtree with all the Deepest Nodes
带有最深节点的最小子树。也就是求最底层叶子节点的最小公共祖先。原题
方法一:用最小公共祖先的求法可以得到。
1 | def subtreeWithAllDeepest(self, root: TreeNode) -> TreeNode: |
1 | def subtreeWithAllDeepest(self, root: TreeNode) -> TreeNode: |
1373. Maximum Sum BST in Binary Tree
找到二叉树中,最大的一个二叉搜索子树所有节点的和。原题
方法一:虽然是个hard题,但是思路很清晰。一个dfs返回时记录这个子树中的最小值,最大值,总和。首次ac的方法。
1 | def maxSumBST(self, root: TreeNode) -> int: |
1 | def maxSumBST(self, root: TreeNode) -> int: |
501. Find Mode in Binary Search Tree
找到二叉搜索树中的众数,可能有多个值。这个树左子树节点是《=当前节点。
方法一:中序遍历改的。将所有节点值按序输出就好找了。
1 | def findMode(self, root): |
968. Binary Tree Cameras
要对一颗二叉树进行监控,一个摄像头可以监控父节点,自身以及子节点。问最少需要多少个摄像头能监控所有节点。
方法一:这题看了题解,实际上有个贪心的解法,通过状态来表示节点是否需要监控。通过后序遍历,子节点的装填判断附近点状态。有时候看到标签上是dp,就被标签上的解法限制住了。
1 | def minCameraCover(self, root: TreeNode) -> int: |
116. Populating Next Right Pointers in Each Node
将一个完美二叉树每层的节点相连。完美二叉树是指所有叶子节点在同一层,每个父节点都有两个子节点。
方法一:stefan.
1 | def connect(self, root: 'Node') -> 'Node': |
117. 填充每个节点的下一个右侧节点指针 II
这题由于要求常数空间复杂度实现,提高了难度。不能使用层序直接做了。对比116题,树不是完美二叉树了。
方法一:指针,cur表示当前层游标,head表示下一层头节点,pre则是下一层的游标。逐个将pre的next和cur的左右子节点相连。
1 | def connect(self, root: 'Node') -> 'Node': |
834. Sum of Distances in Tree](https://leetcode.com/problems/sum-of-distances-in-tree/)
给定一个无向、连通的树。树中有 N 个标记为 0…N-1 的节点以及 N-1 条边 。返回一个表示节点 i 与其他所有节点距离之和的列表 ans。
1 | 输入: N = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]] |
方法一:dfs. @lee215的方法。 属实是一道hard题,看了题解才明白。对于任意节点,可以从O(n)获取所有的距离之和。但是如果每个节点都做一遍dfs,O(n^2)明显会超时。这样思考,当根节点在无向图中移动时,比如从0到2,那么与移动方向相同的节点,所有节点距离都少了1;与之反向的节点距离都+1。那么如果知道了2节点的子树(包含2节点)一共有多少个节点,就知道了距离是如何变化的。还需要明白一件事,res[root] = res[child] + count[child]。比如以0位父节点,在0的右子树部分距离和为
res[2] + count[2],count表示2子树有多少个节点。因为对于2中所有的节点到2的距离都包含在了
res[2]`中,那么需要计算到0的距离,就是所有的节点再+1。我们以0位根节点,在通过0算其他的距离和。知道了这些规律,先进行一次后序遍历更新更新res[0]和count。然后进行先序遍历更新0的各个子节点的距离和。
1 | def sumOfDistancesInTree(self, N: int, edges: List[List[int]]) -> List[int]: |
655. Print Binary Tree
打印二叉树。
1 | Input: |
方法一:iterative.
1 | def printTree(self, root: TreeNode) -> List[List[str]]: |
方法二:递归法也很清晰。
1 | def printTree(self, root: TreeNode) -> List[List[str]]: |
方法三:自己写得方法,逐层遍历,逐层更新。
1 | def printTree(self, root: Optional[TreeNode]) -> List[List[str]]: |
307. Range Sum Query - Mutable
可变区间查询。
1 | Given nums = [1, 3, 5] |
方法一:标准的线段树。
1 | class Node: |
652. Find Duplicate Subtrees
找到重复的子树结构,相同子树返回任意节点。
1 | Input: root = [1,2,3,4,null,2,4,null,null,4] |
方法一:序列化+哈希。
1 | def findDuplicateSubtrees(self, root: TreeNode) -> List[TreeNode]: |
方法二:使用三元组,这里的defaultdict写法很独特。
1 | def findDuplicateSubtrees(self, root: TreeNode) -> List[TreeNode]: |
1028. Recover a Tree From Preorder Traversal
通过前序遍历重建二叉树。
1 | Input: S = "1-2--3--4-5--6--7" |
方法一:迭代。使用一个栈来辅助。当栈长度大于深度时,将子节点出栈。然后优先安装左子节点。
1 | def recoverFromPreorder(self, S: str) -> TreeNode: |