树的题目中递归用的比较多(可是递归是真难弄 我🍂了,此次也忘记加上题目了,下次注意🤥node
class Solution: def buildTree(self, preorder, inorder) -> TreeNode: if len(preorder) == 0 or len(inorder) == 0: return # 若是只有一个确定是"根"就直接返回 if len(preorder) == 1 and len(inorder) == 1: return TreeNode(preorder[0]) root = TreeNode(preorder[0]) ind = inorder.index(preorder[0]) # 递归构造左子树部分 root.left = self.buildTree(preorder[1:ind+1], inorder[:ind]) # 递归构造右子树部分 root.right = self.buildTree(preorder[ind+1:], inorder[ind+1:]) return root
""" 递归构造, 中序遍历为左根右,后序遍历为左右根。 每次找到根的位置再递归去构建左右子树。 """ class Solution: def buildTree(self, inorder, postorder) -> TreeNode: if len(inorder) == 0 or len(postorder) == 0: return if len(inorder) == 1 and len(postorder) == 1: return TreeNode(postorder[-1]) root = TreeNode(postorder[-1]) ind = inorder.index(postorder[-1]) root.left = self.buildTree(inorder[:ind], postorder[:ind]) root.right = self.buildTree(inorder[ind+1:], postorder[ind:-1]) return root
# 109. 有序链表转换二叉搜索树 """ 将链表想象成一根绳子,每次都抓住最中间的部分做为根,递归实现。(相似于中序、后序还原一颗树) """ class Solution: def sortedListToBST(self, head: ListNode) -> TreeNode: lNum = [] while head: lNum.append(head.val) head = head.next def DFS(l): if len(l) == 0: return if len(l) == 1: return TreeNode(l[0]) rootInd = len(l) // 2 root = TreeNode(l[rootInd]) root.left = DFS(l[:rootInd]) root.right = DFS(l[rootInd+1:]) return root return DFS(lNum)
class Solution: def hasPathSum(self, root, sum: int) -> bool: def DFS(root, s): if not root: return False if not root.left and not root.right and s - root.val == 0: return True return DFS(root.left, s-root.val) or DFS(root.right, s-root.val) return DFS(root, sum)
class Solution: def increasingBST(self, root: TreeNode) -> TreeNode: if not root: return Inor = [] # 先中序遍历获取序列 def Inorder(root): if not root: return Inorder(root.left) Inor.append(root.val) Inorder(root.right) Inorder(root) rootNode = TreeNode(Inor.pop(0)) # tree存放已经建好的结点 tree = [rootNode] # 建树 while len(Inor) != 0: node = tree.pop(0) tmp = Inor.pop(0) newnode = TreeNode(tmp) node.right = newnode tree.append(newnode) return rootNode
""" 想不出来递归就想特殊状况: ` 空树如何处理 ` 只有一个根节点的如何处理 ` 有一个根节点一个左节点一个右节点的如何处理 """ class Solution: def binaryTreePaths(self, root): res = [] def DFS(root, tmp): if not root: return if not root.left and not root.right: res.append((tmp+[str(root.val)]).copy()) return # 不改变原始tmp的状态 if root.left: DFS(root.left, tmp+[str(root.val)]) if root.right: DFS(root.right, tmp+[str(root.val)]) DFS(root, []) return ["->".join(tmp) for tmp in res]
""" 一开始考虑的是利用BFS获取全部的叶子节点,但这是不行的,由于BFS是一层一层来的全部最后叶子结点序列的顺序会和期待的结果不一样。 再考虑使用DFS,由于题目规定的是从左到右的叶子结点的顺序因此应该是DFS。 """ class Solution: def leafSimilar(self, root1: TreeNode, root2: TreeNode) -> bool: def DFS(root, tmp): if not root: return [] if not root.left and not root.right: tmp.append(root.val) if root.left: DFS(root.left, tmp) if root.right: DFS(root.right, tmp) return tmp res1 = DFS(root1, []) # print(res1) res2 = DFS(root2, []) # print(res2) if res1 == res2: return True return False
""" 根不变,左子树变成右子树,右子树变成左子树。 """ class Solution: def invertTree(self, root: TreeNode) -> TreeNode: if not root: return newroot = TreeNode(root.val) newroot.left = self.invertTree(root.right) newroot.right = self.invertTree(root.left) return newroot
""" 并无用到题中给出的二叉搜索树的良好性质。 先记录每个节点的父节点,再从目标节点一直走到根节点,判断两个目标节点走到根节点路径中重合的第一个点 """ class Solution: def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': if not root: return Q = [root] # parent[i]表示值为i的结点的父节点 parent = dict() parent[root.val] = TreeNode(-1) while len(Q) != 0: node = Q.pop(0) if node.left: parent[node.left.val] = node Q.append(node.left) if node.right: parent[node.right.val] = node Q.append(node.right) # 找到从目标节点到根节点的路径 def findPath(tarNode, res): res.append(tarNode.val) while parent[tarNode.val].val != -1: res.append(parent[tarNode.val].val) tarNode = parent[tarNode.val] return res # 找到两条路径的交叉点 p1 = findPath(p, []) p2 = findPath(q, []) # 长度段的表示应该是位于上面一些的 if len(p1) > len(p2): p1, p2 = p2, p1 for i in p1: if i in p2: return TreeNode(i) return TreeNode(-1)
""" 符合二叉搜索树的版本 根据二叉搜索树的性质(左小右大) (树划分为:根 左子树 右子树) 1. 若是两个结点位于同一颗子树上,那么要么两个的值都大于根 or 两个的值都小于根 2. 若是两个结点分别位于不一样的子树上,那么其最近的结点必定是根结点 """ class Solution: def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': # 同时位于左子树 if p.val < root.val and q.val < root.val: return self.lowestCommonAncestor(root.left, p, q) # 同时位于右子树 if p.val > root.val and q.val > root.val: return self.lowestCommonAncestor(root.right, p, q) # 一个子树一个,其最近祖先必然是根 return root
""" 实质仍是在求二叉树的全部路径 Tip: 递归的时候保证每次返回的时候不改变参数值 """ class Solution: def sumNumbers(self, root: TreeNode) -> int: res = [] def DFS(root, tmp): if not root: return if not root.left and not root.right: res.append((tmp + [str(root.val)]).copy()) return if root.left: DFS(root.left, tmp + [str(root.val)]) if root.right: DFS(root.right, tmp + [str(root.val)]) DFS(root, []) s = 0 for i in res: while len(i) != 0 and i[0] == '0': i.pop(0) if len(i) == 0: continue s += eval("".join(i)) return s