代码随想录算法训练营第十三天

10 阅读4分钟

二叉树理论

典型二叉树

  • 满二叉树:顾名思义
  • 完全二叉树:特点是除了底层没填满,其他各层均是满节点的树,且底层节点都聚集在左边位置
  • 二叉搜索树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树
  • 平衡二叉搜索树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是平衡二叉 树

二叉树的遍历方式

  1. 深度优先遍历(DFS):
    • 前序遍历
    • 中序遍历
    • 后序遍历
  2. 广度优先遍历(BFS):
    • 层序遍历

二叉树的定义

class TreeNode(self,val,left=None,right=None):
    self.val=val
    self.left=left
    self.right=right

二叉树的递归遍历

在写递归的时候,要严格按照三要素来写,确保自己每次写都有一定的逻辑。

  • 确定递归函数的参数和返回值
  • 确定终止条件
  • 确定单层递归的逻辑

前序遍历

# 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 __init__(self):
        self.res=[]
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        self.traverse(root)
        return self.res
    
    def traverse(self,root):
        if root==None:
            return 
        self.res.append(root.val)
        left=self.traverse(root.left)
        right=self.traverse(root.right)

中序遍历

# 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 __init__(self):
       self.res=[]
   def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
       self.traverse(root)
       return self.res
   def traverse(self,root):#遍历的函数
       if root==None:
           return 0
       left=self.traverse(root.left)
       self.res.append(root.val)
       right=self.traverse(root.right)

后序遍历

# 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 __init__(self):
       self.res=[]
   def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
       self.traverse(root)
       return self.res
   def traverse(self,root):
       if root is None:
           return 0
       # 后序遍历:左右中
       left=self.traverse(root.left)
       right=self.traverse(root.right)
       self.res.append(root.val)

二叉树的迭代遍历

递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。

前序

这里注意要先加入右节点,再加入左节点;因为根据栈的特性,这样先弹出来的是左节点

# 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]:
        if not root:
            return []
        stack=[root]
        result=[]
        while stack:
            node=stack.pop()
            result.append(node.val)
            if node.right:
                stack.append(node.right)
            if node.left:
                stack.append(node.left)
        return result

后序

先说一下后序,因为前序和后序的迭代逻辑是一样的,只需要略微修改一下入栈顺序即可.
后序的顺序是左右中,我们只需要将入栈顺序写成中右左,然后反转result即可

# 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]:
        if not root:
            return []
        stack=[root]
        result=[]
        while stack:
            node=stack.pop()
            result.append(node.val)
            if node.left:
                stack.append(node.left)
            if node.right:
                stack.append(node.right)
        return list(reversed(result))

中序

中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了处理顺序和访问顺序是不一致的。
(后面还得回顾)

# 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]:
        if not root:
            return []
        stack=[]
        result=[]
        cur=root
        while cur or stack:
            if cur:
                stack.append(cur)
                cur=cur.left
            else:
                cur=stack.pop()
                result.append(cur.val)
                cur=cur.right
        return result

二叉树层序遍历

199.二叉树的右视图

和基本的层序遍历基本一模一样,主要就是判断每一层最后一个元素

# 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
from collections import deque
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        if root is None:
            return []
        q=deque()
        q.append(root)
        res=[]
        while q:
            sz=len(q)
            for i in range(sz):
                node=q.popleft()
                if i==sz-1:
                    res.append(node.val)
                if node.left:
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
        return res

637.二叉树的层平均值

一遍过,爽~

# 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
from collections import deque
class Solution:
    def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
        if not root:
            return []
        q=deque()
        q.append(root)
        res=[]
        
        while q:
            sz=len(q)
            level=[]
            avg=0
            cnt=0
            for i in range(sz):
                cnt+=1
                cur=q.popleft()
                level.append(cur.val)
                if cur.left:
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
            avg=sum(level)/cnt
            res.append(avg)
        return res

429.N叉树的层序遍历

"""
# Definition for a Node.
class Node:
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        self.val = val
        self.children = children
"""
from collections import deque
class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root:
            return []
        q=deque()
        q.append(root)
        res=[]
        while q:
            level=[]
            sz=len(q)
            for i in range(sz):
                cur=q.popleft()
                level.append(cur.val)
                for child in cur.children:
                    q.append(child)
            res.append(level)
        return res

116.填充每个节点的下一个右侧节点指针

"""
# Definition for a Node.
class Node:
    def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""
from collections import deque
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return root
        q=deque()
        q.append(root)
        while q:
            sz=len(q)
            prev=None
            for i in range(sz):
                cur=q.popleft()
                if prev:
                    prev.next=cur
                prev=cur
                if cur.left:
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
        return root

111.二叉树的最小深度

# 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
from collections import deque
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        q=deque()
        q.append(root)
        depth=0
        while q:
            sz=len(q)
            depth+=1
            for i in range(sz):
                cur=q.popleft()
                if not cur.left and not cur.right:
                    return depth
                if cur.left:
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
        return depth