python实现Leetcode树相关题(重建二叉,子结构,镜像,对称,层次遍历,深度,和/路径,第k大节点,最近公共祖先)

1.重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路:递归
1.直接递归左右子树的时候切分前序和中序。
pos是获取在中序遍历里根节点的位置
python里可以选择用dict存储,也可以用list.index(值)得到索引

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        if len(pre)==0:
            return None
        # write code here
        root=TreeNode(pre[0])
        pos=tin.index(pre[0])
        root.left=self.reConstructBinaryTree(pre[1:pos+1], tin[:pos])
        root.right=self.reConstructBinaryTree(pre[pos+1:], tin[pos+1:])
        return root

2.或者根据子树的根节点在前序中的位置/子树在中序中的左边界/子树在中序中的右边界
“pos-left+root+1”,其实就是右子树根节点=(中序根节点坐标-中序左边界)+先序根节点坐标+1,其中括号内=左子树长度
left:中序左边界
right:中序右边界
root:前序根节点坐标
pos:中序根节点坐标

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
        def recur(root, left, right):
            if left > right: return                               # 递归终止
            node = TreeNode(pre[root])                       # 建立根节点
            pos = tin.index(pre[root]) # 划分根节点左子树右子树
            node.left = recur(root + 1, left, pos - 1)              # 开启左子树递归
            node.right = recur(pos - left + root + 1, pos + 1, right) # 开启右子树递归
            return node                                           # 回溯返回根节点
        return recur(0, 0, len(tin) - 1)

2.树的子结构

在这里插入图片描述

def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:

首先,树a或者树b为空均返回False
check检查b是否是a的子树||b是否是a左子树的子树||b是否是a右子树的子树(or)

   def check(self,a,b):

在具体检查的时候:如a为空,匹配不上,b为空则可以匹配的上,当a,b均不为空的时候,检查a的根节点,left,right是否等于b的根节点,left,right.(and)

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

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



或者

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

class Solution:
    def check(self,a,b):
        if not b :return True
        if not a :return False
        return a.val==b.val and self.check(a.left,b.left) and self.check(a.right,b.right) 

    def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
        if not A or not B: return False
        return self.check(A,B) or self.isSubStructure(A.left,B) or self.isSubStructure(A.right,B)

注意:在check里需要注意,先判断有可能作为子树的b的情况,如果为空直接返回true了。如果先判断a的非空情况,如果a为空,有可能b也为空,但还没来得及判断就直接返回False了。

3.二叉树的镜像

题目:在这里插入图片描述
镜像
在这里插入图片描述
思路1:递归
注意,如果是其他的语言需要暂存root.left再交换,python可以利用平行赋值的写法(即 a, b = b, a ),可省略暂存操作。其原理是先将等号右侧打包成元组 (b,a),再序列地分给等号左侧的 a, b 序列。

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

class Solution:
    def mirrorTree(self, root: TreeNode) -> TreeNode:
        # 直接交换
        if not root:return None
        root.left,root.right=self.mirrorTree(root.right),self.mirrorTree(root.left)
        return root
  

思路2:辅助stack
利用栈(或队列)遍历树的所有节点 node ,并交换每个 node 的左 / 右子节点。

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

class Solution:
    def mirrorTree(self, root: TreeNode) -> TreeNode:
        if not root:return None
        stack=[root]
        while stack:
            node=stack.pop()
            if node.left:stack.append(node.left)
            if node.right:stack.append(node.right)
            node.left,node.right=node.right,node.left
        return root

4.对称的二叉树

在这里插入图片描述
对称
在这里插入图片描述
思路:

isSymmetric(root) :

特例处理: 若根节点 root 为空,则直接返回 true。
返回值: 即 recur(root.left, root.right) ;

recur(L, R) :

终止条件:
当 L 和 R同时越过叶节点: 此树从顶至底的节点都对称,因此返回 true;

 if not left and not right: return True

当 L或 R 中只有一个越过叶节点: 此树不对称,因此返回 false ;
当节点 L 值 != 节点 R 值: 此树不对称,因此返回 false;

 if not left or not right or left.val!=right.val:return False

递推工作:
判断两节点 L.left 和 R.right 是否对称,即 recur(L.left, R.right) ;
判断两节点L.right 和 R.left 是否对称,即 recur(L.right, R.left) ;
返回值: 两对节点都对称时,才是对称树,因此用与逻辑符 &连接

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

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

5.层次遍历

5-1.输出层次遍历结果

在这里插入图片描述
用一个辅助队列

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

class Solution:
    def levelOrder(self, root: TreeNode) -> List[int]:
        if not root:return []
        res,queue=[],[root]
        while queue:
            node=queue.pop(0)
            res.append(node.val)
            if node.left:queue.append(node.left)
            if node.right:queue.append(node.right)
        return res

5-2.每层单独输出

在这里插入图片描述

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

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:return []
        res,queue=[],[root]
        while queue:
            temp=[]
            for _ in range(len(queue)):
                node=queue.pop(0)
                temp.append(node.val)
                if node.left: queue.append(node.left)
                if node.right:queue.append(node.right)
            res.append(temp)
        return res 

5-3.之字形输出

在这里插入图片描述

import collections
q=collections.deque()
q.append(xxx)
q.appendleft(xxxx)
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

#
# 
# @param root TreeNode类 
# @return int整型二维数组
import collections
class Solution:
    def zigzagLevelOrder(self , root ):
        # write code here
        if not root:return []
        queue,res=[root],[]
        while queue:
            temp=collections.deque()
            for _ in range(len(queue)):
                node=queue.pop(0)
                if len(res)&1:
                    temp.appendleft(node.val)
                else:
                    temp.append(node.val)
                if node.left:queue.append(node.left)
                if node.right:queue.append(node.right)
            res.append(temp)
        return res
     
                

6.二叉树的最大深度

求给定二叉树的最大深度,
最大深度是指树的根结点到最远叶子结点的最长路径上结点的数量。
思路1
DFS,递归
左右子树的最深深度+1即可

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

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

思路2
BFS,层次遍历计算深度

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

class Solution:
    #BFS
    def maxDepth(self, root: TreeNode) -> int:
        if not root:return 0
        queue=[root]
        depth=0
        while queue:
            for _ in range(len(queue)):
                node=queue.pop(0)
                if node.left:queue.append(node.left)
                if node.right:queue.append(node.right)
            depth+=1
        return depth

7-1.和为target的路径

在这里插入图片描述

解题思路:
先序遍历: 按照 “根、左、右” 的顺序,遍历树的所有节点。
路径记录: 在先序遍历中,记录从根节点到当前节点的路径。当路径为 ① 根节点到叶节点形成的路径 且 ② 各节点值的和等于目标值 sum 时,将此路径加入结果列表。
在这里插入图片描述

**注意:**值得注意的是,记录路径时若直接执行 res.append(path) ,则是将 path 对象加入了 res ;后续 path 改变时, res 中的 path 对象也会随之改变。

正确做法:res.append(list(path)) ,相当于复制了一个 path 并加入到 res 。

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

#
# 
# @param root TreeNode类 
# @param sum int整型 
# @return int整型二维数组
#
class Solution:
    def pathSum(self , root , sum ):
        res,path=[],[]
        def recur(root,sum):
            if not root:return 
            path.append(root.val)
            sum-=root.val
            if sum==0 and not root.left and not root.right:
                res.append(list(path))
            recur(root.left,sum)
            recur(root.right,sum)
            path.pop()
        recur(root,sum)
        return res
            
            

7-2 所有路径和

在这里插入图片描述

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

#
# 
# @param root TreeNode类 
# @return int整型
#
class Solution:
    def sumNumbers(self , root ):
        def recur(root,sum):
            if not root:return 0
            sum=sum*10+root.val
            if not root.left and not root.right:
                return sum
            return recur(root.left,sum)+recur(root.right, sum)
        sum=0
        return recur(root,sum)
                

8.二叉搜索树的第k个节点

在这里插入图片描述
思路:二叉搜索树如果按照【右,根,左】顺序取,则从大到小排,取第k-1个值即可

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

class Solution:
    def kthLargest(self, root: TreeNode, k: int) -> int:
        res=[]
        def reverse_zx(root):
            if not root:return
            reverse_zx(root.right)
            res.append(root.val)
            reverse_zx(root.left)
        reverse_zx(root)
        return res[k-1]

9. 最近公共祖先

9-1. 二叉搜索树最近公共祖先

在这里插入图片描述

本题给定了两个重要条件:① 树为 二叉搜索树 ,② 树的所有节点的值都是 唯一 的。根据以上条件,可方便地判断 p,q 与 root的子树关系,即:

若 root.val < p.val,则 p 在 root 右子树 中;
若 root.val > p.val,则 p在 root 左子树 中;
若 root.val = p.val,则 p 和 root指向 同一节点 。

思路:
循环搜索: 当节点 root 为空时跳出;
当 p, q都在 root的 右子树 中,则遍历至 root.right ;
否则,当 p, q 都在 rootroot 的 左子树 中,则遍历至 root.left;
否则,说明找到了 最近公共祖先 ,跳出。
返回值: 最近公共祖先 root 。


class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if p.val > q.val: p, q = q, p # 保证 p.val < q.val
        while root:
            if root.val < p.val: # p,q 都在 root 的右子树中
                root = root.right # 遍历至右子节点
            elif root.val > q.val: # p,q 都在 root 的左子树中
                root = root.left # 遍历至左子节点
            else: break
        return root

递归也可

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if root.val < p.val and root.val < q.val:
            return self.lowestCommonAncestor(root.right, p, q)
        if root.val > p.val and root.val > q.val:
            return self.lowestCommonAncestor(root.left, p, q)
        return root

9-2. 二叉树的最近公共祖先

在这里插入图片描述

输出节点or输出节点值
在这里插入图片描述
考虑通过递归对二叉树进行后序遍历,当遇到节点 p或 q时返回。从底至顶回溯,当节点 p, q 在节点 root 的异侧时,节点 root即为最近公共祖先,则向上返回 root。
输出节点

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

class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        if not root or root==p or q==root: return root
        left=self.lowestCommonAncestor(root.left,p,q)
        right=self.lowestCommonAncestor(root.right,p,q)
        if not left: return right 
        if not right: return left 
        return root

输出节点值

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

#
# 
# @param root TreeNode类 
# @param o1 int整型 
# @param o2 int整型 
# @return int整型
#
class Solution:
    def lowestCommonAncestor(self , root , o1 , o2 ):
        if not root:return -1
        if o1==root.val or o2==root.val:return root.val
        left=self.lowestCommonAncestor(root.left, o1, o2)
        right=self.lowestCommonAncestor(root.right, o1, o2)
        if left==-1:return right
        if right==-1: return left
        return root.val
        

2021-03 未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值