珍宝鸭的力扣练习(4):N叉树题目合集********

前言!

此时此刻我的乖老婆在和我生气,我也好难受,我怕老婆嫌弃我不要我,很怕有会分手的那天,你如果在偷偷看我博博的话,俺想是说我欠着你很多!一辈子都还不了你,我会一辈子对你好,把心放在肚子里吧宝贝。

类型1:输出树的遍历

例题1:输出前序遍历

给定一个 N 叉树,返回其节点值的前序遍历。
例如,给定一个 3叉树 :
返回其前序遍历: [1,3,5,6,2,4 ]。在这里插入图片描述
方法1:递归(最简单的做法)

class Solution(object):
    def preorder(self, root):
        if root==None:
           return None
        result=[]
        def pres(root):
            if root.val!=None:
                result.append(root.val)#先自身
                for node in root.children:#再从左到右的各孩子
                   pres(node)
        pres(root)
        return result

方法2:迭代(困难)
首先贴上代码块

class Solution(object):
    def preorder(self, root):
        """
        :type root: Node
        :rtype: List[int]
        """

        if root is None:
            return []
        stack = [root]                               
        out = []
        while stack:
            temp = stack.pop()                          
            out.append(temp.val)
            if temp.children:                           
                for item in temp.children[::-1]:
                    stack.append(item)
        return out

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

例题2:输出层次遍历

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if root==None: return []
        stack,result,layer= [root],[],[0]
        while stack:
            tmp=[]
            for i in range(len(stack)):
                s=stack.pop(0)
                tmp.append(s.val)
                if s.left:  
                    stack.append(s.left)
                if s.right: 
                    stack.append(s.right)
            result.append(tmp)       

        return result

例题3:输出中序遍历

给定一个二叉树的根节点 root ,返回它的 中序 遍历。

class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        result=[]
        def DFS(cur):
            if not cur: return 
            DFS(cur.left)
            result.append(cur.val)
            DFS(cur.right)
        DFS(root)
        return result

类型4:输出后序遍历

"""
# Definition for a Node.
class Node(object):
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution(object):
    def postorder(self, root):
        """
        :type root: Node
        :rtype: List[int]
        """
        result=[]
        def DFS(root):
            if not root: return 
            for c in root.children:
                DFS(c)
            result.append(root.val)
        DFS(root)
        return result

类型2:重建二叉树

例题1:根据前序与中序遍历

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
列:
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回:
在这里插入图片描述

二叉树的前序遍历顺序是:根节点、左子树、右子树,每个子树的遍历顺序同样满足前序遍历顺序。
二叉树的中序遍历顺序是:左子树、根节点、右子树,每个子树的遍历顺序同样满足中序遍历顺序。

前序遍历的第一个节点是根节点,只要找到根节点在中序遍历中的位置,在根节点之前被访问的节点都位于左子树,在根节点之后被访问的节点都位于右子树,由此可知左子树和右子树分别有多少个节点。

通过中序遍历得知左子树和右子树的节点数量之后,可以根据节点数量得到前序遍历中的左子树和右子树的分界,因此可以进一步得到左子树和右子树各自的前序遍历和中序遍历,可以通过递归的方式,重建左子树和右子树,然后重建整个二叉树。

class Solution(object):
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if not preorder:
            return None
        #创建当前节点
        node = TreeNode(preorder[0]) 
        #查找当前的根节点在中序遍历中的位置
        index = inorder.index(preorder[0]) 
        # 划分左右子树
        left_pre = preorder[1:index+1]
        left_in = inorder[:index]
        right_pre = preorder[index+1:]
        right_in = inorder[index+1:]
        # 遍历创建子树
        node.left = self.buildTree(left_pre, left_in)
        node.right = self.buildTree(right_pre, right_in)
        # 返回当前节点
        return node

例题2:有序数组构造高度平衡二叉树

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
在这里插入图片描述
直观地看,我们可以选择中间数字作为二叉搜索树的根节点,这样分给左右子树的数字个数相同或只相差 1,可以使得树保持平衡。
确定平衡二叉搜索树的根节点之后,其余的数字分别位于平衡二叉搜索树的左子树和右子树中,左子树和右子树分别也是平衡二叉搜索树,因此可以通过递归的方式创建平衡二叉搜索树。

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
        def helper(left, right):
            if left > right:
                return None

            # 总是选择中间位置左边的数字作为根节点
            mid = (left + right) // 2

            root = TreeNode(nums[mid])
            root.left = helper(left, mid - 1)
            root.right = helper(mid + 1, right)
            return root

        return helper(0, len(nums) - 1)

例题3:根据完整的前序遍历

将完整的前序遍历构造为2叉树。

完整的前序遍历结果为:【1,2,Null,Null,3,4,5】

class Solution:
    def deserialize(self, data):
        """Decodes your encoded data to tree.
        
        :type data: str
        :rtype: TreeNode
        """
        if not data: return
        if data[0]==None: 
            data.pop(0)
            return 
        root=TreeNode(data.pop(0))
        if data:  
            root.left=self.deserialize(data)
        if data:
            root.right=self.deserialize(data)
        return root

类型3: 深度

例题1:N 叉树的最大深度

给定一个 N 叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。
例如,给定一个 3叉树 :
在这里插入图片描述
DFS深度优先搜索——类似于树的先根遍历,是树的先根遍历的推广

简述算法过程

1、任选一顶点作始点 v ,访问该顶点
2、沿深度方向,依次遍历 v 的未访问邻接点——直到本次遍历结束
3、一次遍历完时,若有未访问顶点:任选一个未访问顶点作起始点,GOTO第2步

算法伪代码:
DFS(dep,、、、) //dep代表目前DFS的深度
{
if(找到解 || 走不下去)
{
//在此处进行相应的操作
return ;
}
枚举下一种情况,DFS(dep+1,、、、)
}
代码为:


class Solution(object):
    def maxDepth(self, root):

        if not root:
             return 0
        depth=1
        self.maxDepth=0
        def DFS(depth,root):
            children=root.children
            if len(children)==0:
                if depth>self.maxDepth:
                   self.maxDepth=depth      
            else:
                for i in range(len(children)):
                    DFS(depth+1,children[i])
        DFS(depth,root)
        return self.maxDepth 


例题2:2叉树的最大深度

在这里插入图片描述

终止条件: 当前节点为空
返回值:
节点为空时,所以返回 0
节点不为空时, 返回左右子树高度的最大值 + 1

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:return 0 
        return 	max(self.maxDepth(root.left),self.maxDepth(root.right))+1

例题3:2叉树的最小深度

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

class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        
        if not root.left and not root.right:
            return 1
        
        min_depth = 10**9
        if root.left:
            min_depth = min(self.minDepth(root.left), min_depth)
        if root.right:
            min_depth = min(self.minDepth(root.right), min_depth)
        
        return min_depth + 1

类型4:两树判断

例题1: B是否为A子结构

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。

输入:A = [3,4,5,1,2], B = [4,1]
输出:true

输入:A = [1,2,3], B = [3,1]
输出:false
若树 B 是树 A 的子结构,则子结构的根节点可能为树 A 的任意一个节点。因此,判断树 B 是否是树A 的子结构,需完成以下两步工作:

1.先序遍历树 A 中的每个节点( isSubStructure(A, B))
2.判断树 A 中 以之为根节点的子树 是否包含树 B ( recur(A, B))

recur(A,B):
当B为None时,表示A已经包含B,返回True
当A为None时,表示A遍历完还没有完全B,返回False
当A.val!=B.val时,表示A不包含B,返回False

class Solution:
    def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
        def recur(A, B):
            if not B: return True
            if not A or A.val != B.val: return False
            return recur(A.left, B.left) and recur(A.right, B.right)

        return bool(A and B) and (recur(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))

鸭子写法:

class Solution(object):
    def isSubStructure(self, A, B):
        def check(A,B):
            if A == None: return False
            if B.left == None and B.right == None:
                if A.val == B.val:
                    return True
                else:
                    return False
            elif B.right == None :
                return check(A.left,B.left)
            elif B.left == None :
                return check(A.right,B.right)
            else: 
                return check(A.left,B.left) and  check(A.right,B.right)


        if A == None or B == None: return False
        if A.val == B.val:
            flag=check(A,B)
            if flag: return True
            else:
                return self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B)
                
        else:
            return self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B)

例题2:两树对称

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        def helper(p,q):
            if (p!=None and q==None) or (p==None and q!=None): return False
            if p==None and q==None: return True
            if p.val!=q.val: 
                return False
            return helper(p.left,q.right) and helper(p.right,q.left)
            
        if root==None or (root.left==None and  root.right==None ): return True
        return helper(root.left,root.right)

类型5:单树操作

例题1: 树的镜像

请完成一个函数,输入一个二叉树,该函数输出它的镜像。
鸭子写法:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def mirrorTree(self, root):
        if root==None: return root
        if root.left or  root.right:
            mid=root.left 
            root.left=root.right
            root.right=mid
            self.mirrorTree(root.left)
            self.mirrorTree(root.right)
        return root
 
class Solution:
    def mirrorTree(self, root: TreeNode) -> TreeNode:
        if not root: return
        tmp = root.left
        root.left = self.mirrorTree(root.right)
        root.right = self.mirrorTree(tmp)
        return root

类型6:判断树的遍历序列

例题1:是否为后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
输入: [1,3,2,6,5]
输出: true

后序遍历顺序:左子节点→右子节点→根
题解:后序遍历序列之中,最后一位是根节点。因为是二叉搜索树,根节点左边的树的值一定小于他,根节点右边的树的值一定大于他,通过迭代判断:
终止条件:len(postorder)==1
判断【1,3,2,6,5】,然后判断【1,3】以及【2,6】

class Solution(object):
    def verifyPostorder(self, postorder):
        """
        :type postorder: List[int]
        :rtype: bool
        """
        if len(postorder)<=1: return True
        root=postorder[-1]
        pre_order,post_order=[],[]
        for i in range(len(postorder)):
            if postorder[i]>root:
                pre_order=postorder[0:i]
                post_order=postorder[i:len(postorder)-1]
                break
            if i==len(postorder)-1:
                pre_order=postorder[0:len(postorder)-1]
    
        if pre_order and max(pre_order)>=root: 
            return False
        elif post_order and   min(post_order)<=root: 
            return False
        return self.verifyPostorder(pre_order) and self.verifyPostorder(post_order)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值