leetcode刷题——二叉树例题

一、层序遍历

遍历记录

107. 二叉树的层序遍历 II

# 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: TreeNode) -> List[List[int]]:
        if not root:return []
        results=[]  # 记录所有层的结果
        from collections import deque
        que=deque([root])  # 存储所有元素的结果

        while que:
            result=[]
            for i in range(len(que)):
                cur=que.popleft()
                result.append(cur.val)
                if cur.left:que.append(cur.left)
                if cur.right:que.append(cur.right)
            results.append(result)

        return results[::-1]   

429. N 叉树的层序遍历

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

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        results=[]
        if not root:return 
        from collections import deque
        que=deque([root])

        while que:
            result=[]
            for i in range(len(que)):
                cur=que.popleft()
                result.append(cur.val)
                if cur.children:que.extend(cur.children)  # 注意这里的children是多个结点,所以要用extend才能够一个个放进que中
            results.append(result)
        return results

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
class Solution:
    def rightSideView(self, root: TreeNode) -> List[int]:
        res=[]  # 记录最终结果
        if not root:return res
        from collections import deque
        que=deque([root])  # 存储所有元素
        # deque相比list的好处是,list的pop(0)是O(n)复杂度,deque的popleft()是O(1)复杂度
        while que:
            cur=que[-1]  # 目前指针指向的节点
            res.append(cur.val)
            for i in range(len(que)):
                cur=que.popleft()
                if cur.left:que.append(cur.left)
                if cur.right:que.append(cur.right)
        return res

求层均值、max、计数

637. 二叉树的层平均值

class Solution:
    def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
        results=[]
        if not root:return 
        from collections import deque
        que=deque([root])

        while que:
            sum=0
            size=len(que)
            for i in range(size):
                cur=que.popleft()
                sum+=cur.val
                if cur.left:que.append(cur.left)
                if cur.right:que.append(cur.right)
            results.append(sum/size)
        return results

515. 在每个树行中找最大值

# 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 largestValues(self, root: TreeNode) -> List[int]:
        if not root:return []
        import math
        from collections import deque
        que=deque([root])
        res=[]

        while que:
            res_max=-math.inf  # 初始化每一层的最大值
            for i in range(len(que)):
                cur=que.popleft()
                res_max=max(res_max,cur.val)
                if cur.left:que.append(cur.left)
                if cur.right:que.append(cur.right)
            res.append(res_max)  # 记录每一层的最大值
        return res

222. 完全二叉树的节点个数

# 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 countNodes(self, root: TreeNode) -> int:
        if not root:return 0
        from collections import deque
        que=deque([root])
        count=0

        while que:
            for i in range(len(que)):
                cur=que.popleft()
                count+=1
                if cur.left:que.append(cur.left)
                if cur.right:que.append(cur.right)
        return count

【递归法】

class Solution:
    def countNodes(self, root: TreeNode) -> int:
        if not root:return 0
        leftNum=0   # 需要先定义变量
        rightNum=0
        if root.left:leftNum = self.countNodes(root.left)  #左
        if root.right:rightNum = self.countNodes(root.right)  #右
        treeNum = leftNum + rightNum + 1 #中
        return treeNum

二叉树、N叉树的最大、最小深度、高度

104.二叉树的最大深度
【法一】层序遍历

# 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: TreeNode) -> int:
        if not root:return 0
        from collections import deque
        que=deque([root])
        length=0
        while que:
            for i in range(len(que)):
                cur=que.popleft()
                if cur.left:que.append(cur.left)
                if cur.right:que.append(cur.right)
            length+=1
        return length

【法二】递归法

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

559. N 叉树的最大深度
【法一】递归法

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""
class Solution:
    def maxDepth(self, root: 'Node') -> int:
        if not root:return 0
        depth=0
        for i in range(len(root.children)):
            depth=max(depth,self.maxDepth(root.children[i]))
        return depth+1

【法二】层序遍历法

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        if not root:return 0
        from collections import deque
        que=deque([root])
        depth=0
        while que:
            for i in range(len(que)):
                cur=que.popleft()
                if cur.children:que.extend(cur.children)
            depth+=1
        return depth

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
class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:return 0
        from collections import deque
        que=deque([(root,1)]) # 每个结点都记录了其对应的树深,之后根据其是否还有子树判断能否作为最小深度
        while que:
            for i in range(len(que)):
                cur,depth=que.popleft()
                # 如果该树没有子树,则找到最小深度,否则继续往下走
                if not cur.left and not cur.right:return depth
                if cur.left:que.append((cur.left,depth+1))
                if cur.right:que.append((cur.right,depth+1))
        return depth

【法二】递归

class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:return 0
        elif not root.left and not root.right:return 1

        min_depth = 10**9  # 用10**9比用math.inf快很多
        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

110.平衡二叉树
二叉树的深度和高度有很大区别

  • 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
  • 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。

在这里插入图片描述
【递归法】
先求高度再判断是否平衡,平衡二叉树则返回高度,不平衡则返回-1

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        # 只要三种不平衡的情况都不是,则是平衡二叉树
        if self.get_height(root) != -1:return True
        else:return False

    # 平衡二叉树则返回高度,不平衡则返回-1
    def get_height(self, root: TreeNode) -> int:
        if not root:return 0
        left_height = self.get_height(root.left)
        right_height = self.get_height(root.right)
        # 不平衡的三种情况:只要有结点不平衡就不平衡
        ## 左结点的子节点存在不平衡
        if left_height== -1:return -1  # 左   # if (left_height := self.get_height(root.left)) == -1
        ## 右结点的子节点存在不平衡
        elif right_height== -1:return -1  # 右
        ## 当前左右结点不平衡
        elif abs(left_height - right_height) > 1:return -1  # 中
        # 平衡,返回树的高度
        else:return 1 + max(left_height, right_height)

填充指针

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

# 层序遍历解法
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:return None
        queue = [root]
        while queue:
            n = len(queue)
            for i in range(n):
                node = queue.pop(0)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
                if i == n - 1:break  # 如果是每层的最后一个就指向null
                node.next = queue[0]  # 如果不是每层的最后一个,就指向它的后一个元素
        return root

# 链表解法
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        first = root
        while first:
            cur = first
            while cur:  # 遍历每一层的节点
                if cur.left: cur.left.next = cur.right  # 找左节点的next
                if cur.right and cur.next: cur.right.next = cur.next.left  # 找右节点的next
                cur = cur.next # cur同层移动到下一节点
            first = first.left  # 从本层扩展到下一层
        return root

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

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

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:return 
        from collections import deque
        que=deque([root])
        while que:
            size=len(que)
            for i in range(size):
                cur=que.popleft()
                if cur.left:que.append(cur.left)
                if cur.right:que.append(cur.right)
                if i==size-1:break
                cur.next=que[0]
        return root

二、反转、对称

这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!
226. 翻转二叉树
【法一】递归法:前序遍历

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None
        root.left, root.right = root.right, root.left #中
        self.invertTree(root.left) #左
        self.invertTree(root.right) #右
        return root

【法二】迭代法:深度优先遍历(前序遍历)

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        # 栈:先进后出,前序遍历的顺序为中左右,故入栈顺序为中右左
        if not root:return 
        stack=[root]
        while stack:
            cur=stack.pop()
            cur.left,cur.right=cur.right,cur.left
            if cur.left:stack.append(cur.left)
            if cur.right:stack.append(cur.right)
        return root

【法三】迭代法:广度优先遍历(层序遍历)

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:return 
        from collections import deque
        que=deque([root])
        while que:
            for i in range(len(que)):
                cur=que.popleft()
                cur.left,cur.right=cur.right,cur.left
                if cur.left:que.append(cur.left)
                if cur.right:que.append(cur.right)
        return root

101. 对称二叉树
【法一】递归法

  • 递归三部曲:写总函数——(1)确定递归函数的参数和返回值写子函数——(2)确定终止条件:比如两个结点为空的情况(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 isSymmetric(self, root: TreeNode) -> bool:
        if not root:return True
        return self.compare(root.left,root.right)
# 子函数
    def compare(self,left,right):
        #首先排除空节点的情况
        if not left and not right :return True
        elif not left and right :return False
        elif left and not right :return False
        #排除了空节点,再排除数值不相同的情况
        elif left.val!=right.val :return False

        #此时就是:左右节点都不为空,且数值相同的情况
        #此时才做递归,做下一层的判断
        #判断外层相等+内层相等
        outside=self.compare(left.left,right.right)
        inside=self.compare(left.right,right.left)
        same=inside and outside
        return same

【法二】迭代法: 使用队列,先进先出

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:return True
        from collections import deque
        que=deque()
        que.append(root.left)
        que.append(root.right)

        while que:
            leftnode=que.popleft()
            rightnode=que.popleft()
            if not leftnode and not rightnode:continue
            elif not leftnode and rightnode:return False
            elif not rightnode and leftnode:return False
            elif leftnode.val!=rightnode.val:return False

            que.append(leftnode.left)
            que.append(rightnode.right)
            que.append(leftnode.right)
            que.append(rightnode.left)
        return True

【法二】迭代法: 使用栈,先进后出

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:return True
        stack=[]
        stack.append(root.left)
        stack.append(root.right)
        while stack:
            rightnode=stack.pop()
            leftnode=stack.pop()
            if not rightnode and not leftnode:continue   # 说明这次检查到的对称点是对称的,比如外侧都是空
            elif not rightnode and leftnode:return False
            elif not leftnode and rightnode:return False
            elif leftnode.val!=rightnode.val:return False

            # 排除以上情况,就继续向下遍历
            stack.append(leftnode.left)
            stack.append(rightnode.right)
            stack.append(leftnode.right)
            stack.append(rightnode.left)
        return True

100. 相同的树
【法一】迭代法,栈

# 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: TreeNode, q: TreeNode) -> bool:
        stack=[]
        stack.extend([p,q])
        while stack:
            righttree=stack.pop()
            lefttree=stack.pop()
            if not righttree and not lefttree:continue
            elif not righttree and lefttree:return False
            elif not lefttree and righttree:return False
            elif lefttree.val!=righttree.val:return False

            stack.append(lefttree.left)
            stack.append(righttree.left)
            stack.append(lefttree.right)
            stack.append(righttree.right)
        return True

【法二】递归法

class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if not p and not q:return True
        elif not p or not q:return False
        elif p.val!=q.val:return False
        return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)

572. 另一棵树的子树
【递归法】

# 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 isSubtree(self, s: TreeNode, t: TreeNode) -> bool:
        if not t and not s:return True
        elif not t or not s:return False
        return self.isSame(s,t) or self.isSubtree(s.left,t) or self.isSubtree(s.right,t)
        
    def isSame(self,p,q):
        if not p and not q:return True
        elif not p or not q:return False
        elif p.val!=q.val:return False
        return p.val==q.val and self.isSame(p.left,q.left) and self.isSame(p.right,q.right)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值