【leetcode】二叉树刷题总结(一)分解思路、遍历思路

本文探讨了递归函数的设计要素,包括确定函数定义、返回值、设置适当的终止条件,以及在处理单层递归和二叉树遍历时的逻辑。同时提及了递归中可能需要额外函数的情况和涉及的回溯技术。
摘要由CSDN通过智能技术生成

前中后序遍历问题

分解思路、遍历思路双解法题目

LeetCode104题 二叉树的最大深度

分解思路-递归法,自底向上收集最大深度,后序位置操作,递归函数有返回值

# 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: Optional[TreeNode]) -> int:
        if not root:
            return 0
        left = self.maxDepth(root.left)
        right = self.maxDepth(root.right)
        return 1 + max(left, 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 maxDepth(self, root: Optional[TreeNode]) -> int:
        self.res = 0
        self.traversal(root, 1)
        return self.res

    def traversal(self, root, depth):
        if not root:
            return
        self.res = max(self.res, depth)
        self.traversal(root.left, depth + 1)
        self.traversal(root.right, depth + 1)

LeetCode111题 二叉树的最小深度

分解思路-递归解法

# 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: Optional[TreeNode]) -> int:
        if not root:
            return 0
        elif not root.left and not root.right:
            return 1
        if root.left and root.right:
            left = self.minDepth(root.left)
            right = self.minDepth(root.right)
        elif root.left:
            left = self.minDepth(root.left)
            right = float('inf')
        elif root.right:
            left = float('inf')  
            right = self.minDepth(root.right)
        return 1 + min(left, 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 minDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        self.res = float('inf')
        self.traversal(root, 1)
        return self.res

    def traversal(self, root, depth):
        if not root:
            return
        if not root.left and not root.right:
            self.res = min(self.res, depth)
        self.traversal(root.left, depth + 1)
        self.traversal(root.right, depth + 1)

层序遍历

# 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: Optional[TreeNode]) -> int:
        from collections import deque
        res = 0
        if root is None:
            return res
        queue = deque([root])
        while queue:
            res += 1
            num = len(queue)
            for i in range(num):
                node = queue.popleft()
                # 层序遍历,可以提前停止搜索
                if node.left is None and node.right is None:
                    return res
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return res

 LeetCode226题 翻转二叉树

分解思路-递归法,自底向上翻转,后序位置操作

# 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 invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return
        left = self.invertTree(root.left)
        right = self.invertTree(root.right)
        root.left = right
        root.right = left
        return root

遍历思路-递归法,自顶向下翻转,前序位置操作

# 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 invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        def traversal(node):
            if node is None or (node.left is None and node.right is None):
                return
            tmp = node.left
            node.left = node.right
            node.right = tmp
            traversal(node.left)
            traversal(node.right)
        traversal(root)
        return root

分解思路解法题目

LeetCode222题 完全二叉树的节点个数

由于完全二叉树的性质,其子树一定有一棵是满的,只消耗 O(logn) 的复杂度而不会继续递归,所以时间复杂度为O(logn) * O(logn)

# 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: Optional[TreeNode]) -> int:
        if root is None:
            return 0
        r = self.getDepth(root)
        if r > 0:
            return 2**r - 1
        else:
            return 1 + self.countNodes(root.left) + self.countNodes(root.right)
    
    def getDepth(self, node):
        left_depth = 1
        left_node = node.left
        right_depth = 1
        right_node = node.right
        while left_node:
            left_depth += 1
            left_node = left_node.left
        while right_node:
            right_depth += 1
            right_node = right_node.right
        if left_depth == right_depth:
            return left_depth
        else:
            return -1

 LeetCode110题 平衡二叉树

分解思路-递归法

# 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 isBalanced(self, root: Optional[TreeNode]) -> bool:
        r = self.getHeight(root)
        if r == -1:
            return False
        else:
            return True

    def getHeight(self, node):
        if node is None:
            return 0
        left_height = self.getHeight(node.left)
        if left_height == -1:
            return -1
        right_height = self.getHeight(node.right)
        if right_height == -1:
            return -1
        if abs(left_height - right_height) > 1:
            return -1
        return 1 + max(left_height, right_height)

LeetCode404题 左叶子之和

分解思路-递归法

# 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 sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        res = 0
        if root.left and not root.left.left and not root.left.right:
            res += root.left.val
        res += self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
        return res

 LeetCode112题 路径总和

# 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 hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if root is None:
            return False
        if root.left is None and root.right is None:
            if targetSum - root.val == 0:
                return True
            else:
                return False
        return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val)

遍历思路解法题目

LeetCode114题 二叉树展开为链表

遍历思路-迭代法

# 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 flatten(self, root: Optional[TreeNode]) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        if not root:
            return
        dummy = TreeNode()
        cur = dummy
        stack = [root]
        while stack:
            node = stack.pop()
            if node.right:
                stack.append(node.right)
                node.right = None
            if node.left:
                stack.append(node.left)
                node.left = None
            cur.right = node     
            cur = node
        dummy.right = None

 LeetCode257题 二叉树的所有路径

遍历思路-递归法,涉及到回溯

# 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 binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        self.res = []
        self.traversal(root, str(root.val))
        return self.res

    def traversal(self, root, path):
        if root.left is None and root.right is None:
            self.res.append(path)
            return
        if root.left:
            self.traversal(root.left, path + '->' + str(root.left.val))
        if root.right:
            self.traversal(root.right, path + '->' + str(root.right.val))

 LeetCode513题 找树左下角的值

遍历思路-递归法,涉及到回溯

# 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 findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        self.max_depth = float('-inf')
        self.res = None
        self.traversal(root, 1)
        return self.res
    
    def traversal(self, root, depth):
        if not root.left and not root.right:
            if depth > self.max_depth:
                self.max_depth = depth
                self.res = root.val
            return
        if root.left:
            self.traversal(root.left, depth + 1)
        if root.right:
            self.traversal(root.right, depth + 1)

 LeetCode113题 路径总和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 pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        self.res = []
        if root is None:
            return self.res
        self.traversal(root, targetSum, [])
        return self.res

    def traversal(self, node, target, tmp_res):
        if node.left is None and node.right is None:
            if target - node.val == 0:
                self.res.append(tmp_res + [node.val])
            return
        if node.left:
            self.traversal(node.left, target - node.val, tmp_res + [node.val])
        if node.right:
            self.traversal(node.right, target - node.val, tmp_res + [node.val])

同时遍历两个树问题

LeetCode100题 相同的树

两个树是相同的树=root值相等 + 左子树相同 + 右子树相同,这样就可以用分解思路解题,同时我们在后序位置,自底向上收集比较结果

分解思路-递归法:

# 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: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        if p is None and q is None:
            return True
        elif (p is not None and q is None) or (p is None and q is not None):
            return False
        elif p.val != q.val:
            return False
        left = self.isSameTree(p.left, q.left)
        right = self.isSameTree(p.right, q.right)
        return left and right

LeetCode101题 对称二叉树

在递归遍历的过程中,要同时遍历左右两个子树,比较的是两个子树的里侧和外侧的元素是否相等,同时我们在后序位置,自底向上收集比较结果

分解思路-递归法:

# 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: Optional[TreeNode]) -> bool:
        return self.is_sym(root.left, root.right)
    
    def is_sym(self, left, right):
        if (left is None and right is not None) or (left is not None and right is None):
            return False
        elif left is None and right is None:
            return True
        elif left.val != right.val:
            return False
        o = self.is_sym(left.left, right.right)
        i = self.is_sym(left.right, right.left)
        return o and i

子树匹配问题-与KMP算法的结合

LeetCode572题 另一棵树的子树

两个子树相同,可以推出它们的深度优先搜索队列相同,但如果两个子树的深度优先搜索队列相同,它们不一定是相同的子树。比如假设s由两个点组成,1是根,2是1的左孩子;t也由两个点组成,1是根,2是1的右孩子,这样一来s和t的深度优先搜索序列相同,但s和t并不相同。

为了解决这个问题,我们可以引入特殊值填充深度优先搜索队列,当一个节点的左孩子或者右孩子为空的时候,就插入这个特殊值,这样深度优先搜索序列就唯一对应一棵树。

处理完之后,就可以通过KMP算法解题,将复杂度降为O(n)。

# 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, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
        next_node_list, next_list = self.getNext(subRoot)
        stack = [root]
        j = 0
        while stack:
            node = stack.pop()
            node_val = node.val if node else 10001
            while j > 0 and next_node_list[j] != node_val:
                j = next_list[j - 1]
            if next_node_list[j] == node_val:
                j += 1
            if j == len(next_list):
                return True
            if node:
                stack.append(node.right)
                stack.append(node.left)
        return False

    def getNext(self, subRoot):
        next_node_list = [subRoot.val]
        next_list = [0]
        j = 0
        stack = [subRoot.right, subRoot.left]
        while stack:
            node = stack.pop()
            node_val = node.val if node else 10001
            while j > 0 and next_node_list[j] != node_val:
                j = next_list[j - 1]
            if next_node_list[j] == node_val:
                j += 1
            next_node_list.append(node_val)
            next_list.append(j)
            if node:
                stack.append(node.right)
                stack.append(node.left)
        return next_node_list, next_list

层序遍历问题 

LeetCode116题 填充每个节点的下一个右侧节点指针

层次遍历

"""
# 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: 'Optional[Node]') -> 'Optional[Node]':
        from collections import deque
        if root is None:
            return
        queue = deque([root])
        while queue:
            num = len(queue)
            for i in range(num):
                node = queue.popleft()
                if i < num - 1:
                    node.next = queue[0]
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return root
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值