LeetCode Cookbook 树(1)

发布于:2022-12-04 ⋅ 阅读:(257) ⋅ 点赞:(0)

CSDN话题挑战赛第2期
参赛话题:算法题解

LeetCode Cookbook 树(1)

正好赶上活动 最近一周把 树 有关的题给做了三十来道,将进行一个系统整理,有关算法的复杂度可以点击链接题目查看,这里就不进行专门的叙述。树 这部分内容挺多的 想分成4~5部分来说,努力,奋斗!

144. 二叉树的前序遍历(model-I 排序)

题目链接:144. 二叉树的前序遍历
题目大意:给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

例如:
在这里插入图片描述

输入:root = [1,null,2,3]
输出:[1,2,3]

解题思路: 两大类方法 三种写法 。方法(一) 深度优先搜索(DFS)、与方法(三) 广度优先搜索(BFS)模板2 通用于前中后遍历, 方法(二) 广度优先搜索(BFS)模板1 适用于前后遍历与层序遍历

方法(一) 深度优先搜索(DFS)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # DFS
        def preOrder(node: Optional[TreeNode]) -> None:
            if node is None: return 
            ans.append(node.val)
            if node.left: preOrder(node.left)
            if node.right: preOrder(node.right)
        
        ans = list()
        preOrder(root)
        return ans

方法(二) 广度优先搜索(BFS)模板1

class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # BFS 模板1
        if root is None: return []
        ans = list()
        q = collections.deque([root])
        while q:
            node = q.pop()
            ans.append(node.val)
            if node.right: q.append(node.right)
            if node.left:q.append(node.left)
        return ans

方法(三) 广度优先搜索(BFS)模板2

class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # BFS 模板2
        ans = list()
        q = collections.deque([(0,root)])
        while q:
            flag,cur = q.pop()
            if cur is None: continue
            if flag == 0:
                q.append((0,cur.right))
                q.append((0,cur.left))
                q.append((1,cur))
            else:
                ans.append(cur.val)
        return ans

94. 二叉树的中序遍历(model-I 排序)

题目链接:94. 二叉树的中序遍历
题目大意:给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

例如:
在这里插入图片描述

输入:root = [1,null,2,3]
输出:[1,3,2]

解题思路: 两大类方法 三种写法 。方法(一) 深度优先搜索(DFS)、与方法(三) 广度优先搜索(BFS)模板2 通用于前中后遍历。

方法(一) 深度优先搜索(DFS)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 前中后 指的都是 根节点所在位置
        # 中序遍历 LDR

        # DFS
        def inOrder(node: Optional[TreeNode]) -> None:
            if node is None: return
            if node.left: inOrder(node.left)
            ans.append(node.val)
            if node.right: inOrder(node.right)  
        ans = list()
        inOrder(root)
        return ans

方法(三) 广度优先搜索(BFS)模板2

class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # BFS 标记 模板
        ans = list()
        q = collections.deque([(0,root)])
        while q:
            flag,cur = q.pop()
            if cur is None: continue
            if flag == 0:
                q.append((0,cur.right))
                q.append((1,cur))
                q.append((0,cur.left))
            else:
                ans.append(cur.val)
        return ans

144. 二叉树的后序遍历(model-I 排序)

题目链接:144. 二叉树的后序遍历
题目大意:给你二叉树的根节点 root ,返回它节点值的 后序 遍历。

例如:
在这里插入图片描述

输入:root = [1,null,2,3]
输出:[3,2,1]

解题思路: 两大类方法 三种写法 。方法(一) 深度优先搜索(DFS)、与方法(三) 广度优先搜索(BFS)模板2 通用于前中后遍历, 方法(二) 广度优先搜索(BFS)模板1 适用于前后遍历与层序遍历

方法(一) 深度优先搜索(DFS)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        
        def postOrder(node: Optional[TreeNode]) -> None:
            if node is None: return 
            if node.left: postOrder(node.left)
            if node.right: postOrder(node.right)
            ans.append(node.val)
        
        ans = list()
        postOrder(root)
        return ans

方法(二) 广度优先搜索(BFS)模板1

class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # BFS 模板1
        if root is None: return []
        ans = list()
        q = collections.deque([root])
        while q:
            node = q.pop()
            if node.left: q.append(node.left)
            if node.right: q.append(node.right)
            ans.append(node.val)
        return ans[::-1]

方法(三) 广度优先搜索(BFS)模板2

        # BFS 模板2
        ans = list()
        q = collections.deque([(0,root)])
        while q:
            flag,cur = q.pop()
            if cur is None: continue
            if flag == 0:
                q.append((1,cur))
                q.append((0,cur.right))
                q.append((0,cur.left))
            else:
                ans.append(cur.val)
        return ans

102. 二叉树的层序遍历(model-I 排序)

题目链接:102. 二叉树的层序遍历
题目大意:给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

例如:
在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

解题思路: 广度优先搜索。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        
        # BFS 模板
        if root is None: return []
        ans = list()
        q = collections.deque([root])
        while q:
            lay,layval = list(),list()
            for node in q:
                layval.append(node.val)
                if node.left: lay.append(node.left)
                if node.right: lay.append(node.right)
            q = lay
            ans.append(layval)
        return ans

107. 二叉树的层序遍历 II(model-I 排序 扩展1)

题目链接:107. 二叉树的层序遍历 II
题目大意:给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

例如:
在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]

解题思路: 广度优先搜索。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:        
        if root is None: return []
        q = collections.deque([root])
        ans = list()
        while q:
            lay,layer = list(),list()
            for node in q:
                layer.append(node.val)
                if node.left: lay.append(node.left)
                if node.right: lay.append(node.right)
            q = lay
            ans.append(layer)
        return ans[::-1]

103. 二叉树的锯齿形层序遍历(model-I 排序 扩展2)

题目链接:102. 二叉树的层序遍历
题目大意:给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

例如:
在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[20,9],[15,7]]

解题思路: 广度优先搜索,加个旗帜。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root is None: return []
        q = collections.deque([root])
        ans = list()
        flag = False
        while q:
            lay,layer = list(),list()
            flag = ~flag 
            for node in q:
                layer.append(node.val)
                if node.left: lay.append(node.left)
                if node.right: lay.append(node.right)
            q = lay
            ans += [layer] if flag else [layer[::-1]]
        return ans

104. 二叉树的最大深度(model-II 深度)

题目链接:104. 二叉树的最大深度
题目大意:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。说明: 叶子节点是指没有子节点的节点。

例如:
给定二叉树 [3,9,20,null,null,15,7],返回它的最大深度 3 。
在这里插入图片描述)

解题思路: 深度优先搜索。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if root is None: return 0
        return max(self.maxDepth(root.left),self.maxDepth(root.right))+1

104. 二叉树的最小深度(model-II 深度)

题目链接:104. 二叉树的最小深度
题目大意:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。

例如:
给定二叉树 [3,9,20,null,null,15,7],返回它的最小深度 2 。
在这里插入图片描述)

解题思路: 稍微复杂些 仍是深度优先搜索。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        if root is None: return 0
        if root.left is None: return self.minDepth(root.right)+1
        if root.right is None: return self.minDepth(root.left)+1
        return min(self.minDepth(root.left),self.minDepth(root.right))+1

563. 二叉树的坡度(model-II 深度 扩展1)

题目链接:104. 二叉树的最大深度
题目大意:给你一个二叉树的根节点 root ,计算并返回 整个树 的坡度 。一个树的 节点的坡度 定义即为,该节点左子树的节点之和和右子树节点之和的 差的绝对值 。如果没有左子树的话,左子树的节点之和为 0 ;没有右子树的话也是一样。空结点的坡度是 0 。整个树 的坡度就是其所有节点的坡度之和。

例如:
给定二叉树 [3,9,20,null,null,15,7],返回它的最大深度 3 。
在这里插入图片描述

输入:root = [1,2,3]
输出:1
解释:
节点 2 的坡度:|0-0| = 0(没有子节点)
节点 3 的坡度:|0-0| = 0(没有子节点)
节点 1 的坡度:|2-3| = 1(左子树就是左子节点,所以和是 2 ;右子树就是右子节点,所以和是 3 )
坡度总和:0 + 0 + 1 = 1

在这里插入图片描述

输出:15
解释:
节点 3 的坡度:|0-0| = 0(没有子节点)
节点 5 的坡度:|0-0| = 0(没有子节点)
节点 7 的坡度:|0-0| = 0(没有子节点)
节点 2 的坡度:|3-5| = 2(左子树就是左子节点,所以和是 3 ;右子树就是右子节点,所以和是 5 )
节点 9 的坡度:|0-7| = 7(没有左子树,所以和是 0 ;右子树正好是右子节点,所以和是 7 )
节点 4 的坡度:|(3+5+2)-(9+7)| = |10-16| = 6(左子树值为 352 ,和是 10 ;右子树值为 97 ,和是 16 )
坡度总和:0 + 0 + 0 + 2 + 7 + 6 = 15

解题思路: 深度优先搜索。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    # py3 定义全局变量 ans
    def __init__(self):
        self.ans = 0

    def findTilt(self, root: Optional[TreeNode]) -> int:
        self.dfs(root)
        return self.ans

    def dfs(self,node:Optional[TreeNode]) -> int:
        if node is None: return 0
        L = self.dfs(node.left)
        R = self.dfs(node.right)
        self.ans += abs(L-R)
        return node.val + L + R

662. 二叉树最大宽度(model-III 宽度 线段树基础)

题目链接:104. 二叉树的最小深度
题目大意:给你一棵二叉树的根节点 root ,返回树的 最大宽度 。树的 最大宽度 是所有层中最大的 宽度 。
每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。题目数据保证答案将会在 32 位 带符号整数范围内。

例如:
在这里插入图片描述

输入:root = [1,3,2,5,3,null,9]
输出:4
解释:最大宽度出现在树的第 3 层,宽度为 4 (5,3,null,9)

在这里插入图片描述

输入:root = [1,3,2,5,null,null,9,6,null,7]
输出:7
解释:最大宽度出现在树的第 4 层,宽度为 7 (6,null,null,null,null,null,7)

解题思路: 两种方法,DFS 以及 BFS。

方法(一)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def widthOfBinaryTree(self, root: Optional[TreeNode]) -> int:

        # DFS
        levelLeft = {}
        def DFS(node: Optional[TreeNode],depth: int,index: int) -> int:
            if node is None: return 0
            if depth not in levelLeft:
                levelLeft[depth] = index
            return max(index - levelLeft[depth]+1,
                    DFS(node.left,depth+1,index*2),
                    DFS(node.right,depth+1,index*2+1))
        return DFS(root,1,1)

方法(二)

class Solution:
    def widthOfBinaryTree(self, root: Optional[TreeNode]) -> int:
        # BFS
        ans = 1
        q =[[root,1]]
        while q:
            tmp = []
            for node,index in q:
                if node.left:
                    tmp.append([node.left,index*2])
                if node.right:
                    tmp.append([node.right,index*2+1])
            ans = max(ans,q[-1][1] - q[0][1] + 1)
            q = tmp
        return ans

100. 相同的树(model-IV)

题目链接:100. 相同的树
题目大意:给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

例如:
在这里插入图片描述

输入:p = [1,2,3], q = [1,2,3]
输出:true

在这里插入图片描述

输入:p = [1,2], q = [1,null,2]
输出:false

解题思路:DFS。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        if p is None and q is None: return True
        elif p and q:
            if p.val != q.val: return False
            else:
                return self.isSameTree(p.left,q.left) and \
                self.isSameTree(p.right,q.right)
        else:
            return False

226. 翻转二叉树(model-IV)

题目链接:226. 翻转二叉树
题目大意:给你一棵二叉树的根节点 root ,返回树的 最大宽度 。树的 最大宽度 是所有层中最大的 宽度 。
每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。题目数据保证答案将会在 32 位 带符号整数范围内。

例如:
在这里插入图片描述

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

在这里插入图片描述

输入:root = [2,1,3]
输出:[2,3,1]

解题思路: DFS。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root is None: return 
        self.invertTree(root.left)
        self.invertTree(root.right)
        root.left,root.right = root.right,root.left
        return root

101. 对称二叉树(model-IV 扩展)

题目链接:101. 对称二叉树
题目大意:给你一个二叉树的根节点 root , 检查它是否轴对称。

例如:
在这里插入图片描述

输入:root = [1,2,2,3,4,4,3]
输出:true

在这里插入图片描述

输入:root = [1,2,2,null,3,null,3]
输出:false

解题思路: 100. 相同的树 + 226. 翻转二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if root is None: return True
        return self.isSametree(self.invertTree(root.left),root.right)
        
    def isSametree(self,p: Optional[TreeNode],q: Optional[TreeNode]) -> bool:
        if p is None and q is None: return True
        elif p and q:
            if p.val != q.val: return False
            else:
                return self.isSametree(p.left,q.left) and \
                self.isSametree(p.right,q.right)
        else:
            return False
        
    def invertTree(self,root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root is None: return 
        self.invertTree(root.left)
        self.invertTree(root.right)
        root.left,root.right = root.right,root.left
        return root

总结

   树 这部分内容很抽象,做起来挺吃力地! 不过加快速度 争取国庆之前 做完整理完,这部分需要好好记一下,树的题有一个总体的解题思路,把复杂的问题往这些简单的基础题上靠,树的难题很大一部分就是题意复杂或包含的基础步骤众多,所以细细品味,加油学习。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到