Leetcode题解 - 树部分简单题目代码+思路(105、106、109、112、897、257、872、226、235、129)

树的题目中递归用的比较多(但是递归是真难弄 我了,这次也忘记加上题目了,下次注意


105. 从前序与中序遍历序列构造二叉树

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

106. 从中序与后序遍历序列构造二叉树

"""
递归构造, 中序遍历为左根右,后序遍历为左右根。
每次找到根的位置再递归去构建左右子树。
"""
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. 有序链表转换二叉搜索树 - 和楼上同样的题型

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

112. 路径总和

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)

897. 递增顺序查找树

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

257. 二叉树的所有路径

"""
想不出来递归就想特殊情况:
` 空树如何处理
` 只有一个根节点的如何处理
` 有一个根节点一个左节点一个右节点的如何处理
"""
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]

872. 叶子相似的树

"""
一开始考虑的是利用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

226. 翻转二叉树

"""
根不变,左子树变成右子树,右子树变成左子树。
"""
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

235. 二叉搜索树的最近公共祖先 - 可以引申到任何结点的最近公共祖先

"""
并没有用到题中给出的二叉搜索树的良好性质。

先记录每一个节点的父节点,再从目标节点一直走到根节点,判断两个目标节点走到根节点路径中重合的第一个点
"""
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

129. 求根到叶子节点数字之和

"""
实质还是在求二叉树的所有路径
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

你可能感兴趣的:(Leetcode题解 - 树部分简单题目代码+思路(105、106、109、112、897、257、872、226、235、129))