二叉树题解

二叉树的主要解法就是递归,DFS深度优先搜索。

这里记录不太熟的题

226.翻转二叉树

先序遍历:根左右

翻转一个二叉树,首先要考虑根节点的左右子节点,将其替换。(根)

然后继续翻转左子树。dfs,左

翻转右子树。右

python 复制代码
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:

        def dfs(node):

            if not node:
                return 
            # 根
            node.left,node.right = node.right,node.left
            # 左,右
            node.left = dfs(node.left)
            node.right = dfs(node.right)
            
            return node
        
        return dfs(root)

101. 对称二叉树

考虑先序遍历

逐层看同一层的两个节点是否对称:都为空; 如果说只有一个为空或者不相等,那就是不对称

根:对根节点和左右子节点判断是否对称

左右:下一层的子节点,也就是左子节点的左边和右子节点的右边以及另外一对是否都通过验证

python 复制代码
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
            
        def dfs(left,right):

            if not left and not right:
                return True
            if not left or not right:
                return False
            if left.val != right.val:
                return False
            
            return dfs(left.left, right.right) and dfs(left.right, right.left)
        
        return dfs(root.left, root.right)

104. 二叉树的最大深度

后序遍历

最大深度就是左右子树中取最大深度+1

先检查左右子树,然后在基础上+1

python 复制代码
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:

        def dfs(root):
            if not root:
                return 0
            
            left = dfs(root.left)
            right = dfs(root.right)

            return max(left,right)+1
        
        return dfs(root)

111. 二叉树的最小深度

后序遍历

跟最大的区别在于要考虑左右子树是否为空的情况,如果为空,就要返回另一个子树的深度+1

python 复制代码
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        #根左右,
        def dfs(root):
            if not root:
                return 0

            left = dfs(root.left)
            right = dfs(root.right)

            if not root.left:
                return right+1
            if not root.right:
                return left+1

            return min(left,right)+1
        
        return dfs(root)

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

后序遍历

分别求左右子树的节点数,然后加上根节点

python 复制代码
class Solution:
    def countNodes(self, root: Optional[TreeNode]) -> int:

        def dfs(root):
            if not root:
                return 0
            
            left = dfs(root.left)
            right = dfs(root.right)

            return left+right+1
        
        return dfs(root)

110. 平衡二叉树

要求任意节点的左右子树的高度差小于等于1

后序遍历

先计算左右子树的高度

然后在跟节点这判断是否平衡,如果不平衡就返回-1,否则返回高度用于上一层的计算

最后看最终返回的是-1还是高度,是-1就不平衡

python 复制代码
class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        
        def dfs(root):
            if not root:
                return 0
            
            left = dfs(root.left)
            right = dfs(root.right)

            if abs(left-right) > 1 or left == -1 or right == -1:
                return -1
            else:
                return max(left,right)+1
        
        return dfs(root) != -1

257. 二叉树的所有路径

先序遍历

回溯

先加上根节点,然后在左右节点上递归。视作一个list,最后转换为字符串

回溯终止条件:叶子节点,也就是没有左右子节点

python 复制代码
class Solution:
    def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        res = []
        path = [str(root.val)]

        def bc(root,path):
            if not root.left and not root.right:
                res.append(path[:])
                return 
            
            if root.left:
                bc(root.left,path+[str(root.left.val)])
            if root.right:
                bc(root.right,path+[str(root.right.val)])
            
        bc(root,path)
        return ["->".join(i) for i in res]

404. 左叶子之和

先序遍历

分别找左右子树的左叶子节点

递归终止条件:没有该节点,到了叶子节点,直接返回0

左子树的左叶子节点需要判断下面是否还有左叶子节点

python 复制代码
class Solution:
    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        
        def dfs(root):
            # 终止条件
            if not root:
                return 0
            if not root.left and not root.right:
                return 0
        
            left = dfs(root.left)
            if root.left and not root.left.left and not root.left.right:
                left = root.left.val
            
            right = dfs(root.right)

            return left+right
        
        return dfs(root)

513. 找树左下角的值

层序遍历,广度优先搜索BFS

遍历每层时将第一个节点作为所求,直到层序遍历结束。

python 复制代码
from collections import deque
from typing import Optional

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left: Optional['TreeNode']=None, right: Optional['TreeNode']=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        if not root:
            return None  # 或者根据题目要求返回其他值
        
        queue = deque([root])
        bottom_left = root.val  # 初始化为根节点值
        
        while queue:
            level_size = len(queue)
            for i in range(level_size):
                node = queue.popleft()
                
                # 在遍历每层时,第一个节点是最左边的
                if i == 0:
                    bottom_left = node.val
                
                # 先添加左子节点,再添加右子节点
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        
        return bottom_left

112. 路径总和

先序遍历+回溯

终止条件:叶子节点且达到目标值

返回值:布尔值

每次进入就减去当前节点值

python 复制代码
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:

        if not root:
            return False

        def bc(root, targetSum):
            # 终止条件
            if not root.left and not root.right and targetSum == 0:
                return True
            # 递归,左子树
            if root.left: # 看左子树是否是
                if bc(root.left, targetSum-root.left.val):
                    return True
            if root.right:
                if bc(root.right, targetSum-root.right.val):
                    return True

            return False

        return bc(root, targetSum-root.val)   

106. 从中序与后序遍历序列构造二叉树

中序:左根右

后序:左右根

思路:先确定根节点,然后递归确定左右子树的根节点,逐步联系起来即可

要确定的是左右子树的list切片范围,用index函数得到

python 复制代码
class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        if not postorder:
            return 
        root = TreeNode(postorder[-1])

        root_index = inorder.index(root.val)
        
        root.left = self.buildTree(inorder[:root_index], postorder[:root_index])
        root.right = self.buildTree(inorder[root_index+1:], postorder[root_index:-1])

        return root

654. 最大二叉树

上题的简化版,根节点是最大值

python 复制代码
class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        if not nums:
            return 
        val = max(nums)
        root = TreeNode(val)
        index = nums.index(val)
        root.left = self.constructMaximumBinaryTree(nums[:index])
        root.right = self.constructMaximumBinaryTree(nums[index+1:])

        return root

617. 合并二叉树

如果有一方为空,那就直接返回另一个就行

都有值,就正常计算

跟上面的一脉相承

python 复制代码
class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:

        if not root1:
            return root2
        if not root2:
            return root1
        
        root = TreeNode(root1.val + root2.val) 
        root.left = self.mergeTrees(root1.left, root2.left)
        root.right = self.mergeTrees(root1.right, root2.right)

        return root

700. 二叉搜索树中的搜索

搜索树,左子树小于根节点 ,右子树大于根节点

先序遍历+递归+二分查找

python 复制代码
class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root: return 
        if root.val == val:
            return root
        elif root.val < val:
            return self.searchBST(root.right, val)
        else:
            return self.searchBST(root.left,val)

98. 验证二叉搜索树

先序遍历,要同时满足左右子树都OK

辅助函数

python 复制代码
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        
        def valid(root, low, high):
            if not root:
                return True
            
            if not (low < root.val < high):
                return False
            
            return valid(root.left, low, root.val) and valid(root.right, root.val, high)
        return valid(root, float("-inf"), float("inf"))

530. 二叉搜索树的最小绝对差

最小差肯定是相邻的两个节点的,采用中序遍历,要有两个变量指示前个和当前节点

使用栈保存中序遍历的结果,左子树遍历完后找根节点进行计算,然后是右子树

python 复制代码
class Solution:
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        # 初始化前一个节点的值为负无穷大
        pre = float("-inf")
        # 当前节点初始化为根节点
        cur = root
        # 使用栈来辅助中序遍历
        stack = []
        # 初始化最小差值为正无穷大
        res = float("inf")

        # 当当前节点不为空或栈不为空时,继续遍历
        while cur or stack:
            # 一直向左遍历,直到到达最左下的节点
            while cur:
                stack.append(cur)  # 将当前节点压入栈中
                cur = cur.left     # 移动到左子节点

            # 弹出栈顶节点,即当前层的最左节点
            cur = stack.pop()
            # 计算当前节点值与前一个节点值的差,并更新最小差值
            res = min(res, cur.val - pre)
            # 更新前一个节点值为当前节点值
            pre = cur.val
            # 移动到右子节点,继续遍历
            cur = cur.right

        # 返回最终的最小绝对差值
        return res

236. 二叉树的最近公共祖先

先序遍历

如果有一个是根节点,那就是根节点

左右子树遍历,查看里面是否有目标

如果都遇到目标,那就是根节点;否则,选择存在的

python 复制代码
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        
        if p == root or q == root or not root:
            return root
        
        left = self.lowestCommonAncestor(root.left, p,q)
        right = self.lowestCommonAncestor(root.right, p,q)

        if left and right:
            return root
        if not left:
            return right
        if not right:
            return left

235. 二叉搜索树的最近公共祖先

跟上题的区别在于二叉搜索可以用二分查找的思想

先序遍历:根,左,右

python 复制代码
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.left,p,q)
        elif root.val < p.val and root.val < q.val:
            return self.lowestCommonAncestor(root.right,p,q)
        else:
            return root

701. 二叉搜索树中的插入操作

先序遍历

左右子树联系起来

python 复制代码
class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        
        if not root:
            return TreeNode(val)
        
        if root.val > val:
            root.left =  self.insertIntoBST(root.left, val)
        if root.val < val:
            root.right =  self.insertIntoBST(root.right, val)

        return root
相关推荐
pen-ai5 分钟前
【数据科学】1. 假设检验
人工智能·算法·机器学习·数据挖掘·数据分析
神秘的土鸡38 分钟前
机器情绪及抑郁症算法
人工智能·算法
鬣主任1 小时前
二叉树的前序遍历---一个简单高效的算法
数据结构·算法
jianbaigreat2 小时前
代码随想录打卡Day22、23、24、25
数据结构·算法
_OLi_2 小时前
力扣 LeetCode 206. 反转链表(Day2:链表)
算法·leetcode·链表
运维&陈同学2 小时前
【HAProxy05】企业级反向代理HAProxy调度算法之静态算法与动态算法
linux·运维·算法·nginx·云原生·负载均衡·lvs·haproxy
weixin_478689762 小时前
【贪心算法】——力扣763. 划分字母区间
算法·leetcode·贪心算法
sp_fyf_20242 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-03
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
友大冰3 小时前
前端开发中的CSS框架:昔日辉煌与新兴潮流
前端·css·算法·开源·tensorflow
nuyoah♂3 小时前
DAY27|贪心算法Part01|LeetCode:455.分发饼干、376. 摆动序列、53. 最大子序和
算法·leetcode·贪心算法