数据结构算法——树

本文深入探讨了树的遍历方法,包括二叉搜索树验证、广度优先搜索、深度优先搜索等核心算法,并通过LeetCode经典题目解析了二叉树的层次遍历、最小深度、最大深度及括号生成等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

该博客结合leetcode原题介绍了“树”常见的题目。

python、C++中的树都是用“红黑树”实现。

在这里插入图片描述

1.1 树的遍历

在这里插入图片描述

在这里插入图片描述

二、例题

2.1 验证二叉搜索树

#Leetcode 98 验证二叉搜索树

(1)利用二叉搜索树的性质
二叉搜索树的中序遍历是一个严格上升序列。
*时间复杂度:O(N),因为每个节点遍历一次
*空间复杂度:O(N),因为存储了中序遍历结果(改进方式:只保留上一个节点,不保存所有遍历结果)

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

class Solution(object):
    def inOrder(self, root):
        if not root:
            return []
        left = self.inOrder(root.left)
        right = self.inOrder(root.right)
        return left + [root.val] + right

    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        inOrderList = self.inOrder(root)
        for i in range(len(inOrderList)-1):
            if inOrderList[i]>=inOrderList[i+1]:
                return False
        return True

(2)递归
同样利用二叉树性质,不断递归,去判断是否满足:左子树<当前节点<右子树。
*时间复杂度:O(N),每个节点访问了一次
*空间复杂度:O(1)


2.2 实现一个对二叉树广度优先搜索的函数

# encoding = utf-8
"""
本脚本用于自己设计一个广度优先算法的函数
"""

# 定义tree的数据类型
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

root = TreeNode(0)
root.left = TreeNode(2)
root.right = TreeNode(4)
root.left.left = TreeNode(5)

def generate_related_nodes(visited, node):
    next_node_list = []
    if node.left not in visited and node.left:
        next_node_list.append(node.left)
    if node.right not in visited and node.right:
        next_node_list.append(node.right)
    return next_node_list

# 广度优先搜索主函数
def BFS(tree, start):
    queue = []
    queue.append(start)
    visited = {}
    visited[start] = 0

    while queue:
        node = queue.pop(0)  # 从数组头部依次拿出每个数据,访问每个节点
        visited[node] = 0  # 记录访问过的节点
        print(node.val)  # 对节点进行一些操作
        queue.extend(generate_related_nodes(visited, node))  # 将下一层节点插在数组尾部


if __name__=="__main__":
    BFS(root, root)

2.3 实现一个对二叉树深度优先搜索的函数

# encoding = utf-8

"""
本脚本用于自己设计一个广度优先算法的函数
"""

# 定义tree的数据类型
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

root = TreeNode(0)
root.left = TreeNode(2)
root.right = TreeNode(4)
root.left.left = TreeNode(5)

visited = {}
def DFS(root):
    visited[root] = 1
    print(root.val)

    for node in [root.left, root.right]:
        if node and node not in visited:
            DFS(node)


if __name__=="__main__":
    DFS(root)

2.4 二叉树的层次遍历

#Leetcode 102 二叉树的层次遍历
(1)BFS
最直观的办法。

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root:
            return []
        queue = [root]
        res = []
        while queue:
            level_size = len(queue)
            cur_level = []
            for _ in range(level_size):
                node = queue.pop(0)
                cur_level.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            res.append(cur_level)
        return res
                    

*时间复杂度O(N)
*空间复杂度O(N)
(2)DFS
记录level,重新复盘

class Solution(object):
    def __init__(self):
        self.ret = []

    def levelOrder(self, root):
        if not root:
            return []
        level = 0
        self.DFS(level, root)
        return self.ret

    def DFS(self, level, root):
        if len(self.ret)<level+1:  # 如果层数不够,先添加一层
            self.ret.append([])
        self.ret[level].append(root.val)
        if root.left:
            self.DFS(level+1, root.left)
        if root.right:
            self.DFS(level+1, root.right)

*时间复杂度O(N)
*空间复杂度O(N)

2.5 二叉树的最小深度

#111. 二叉树的最小深度
目标:找最小的叶子节点
(1)BFS

def generate_related_nodes(visited, node):
    next_node_list = []
    for next_node in [node[0].left, node[0].right]:
        if next_node and next_node not in visited:
            next_node_list.append([next_node, node[1]+1])
    return next_node_list

class Solution(object):
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root: return 0
        visited = {}
        level = 1
        queue = []
        visited[root] = 1
        queue.append([root, level])
        while queue:
            node = queue.pop(0)
            if not node[0].left and not node[0].right:
                return node[1]
            queue.extend(generate_related_nodes(visited, node))

(2)DFS
要记录深度level,更新max和min

import sys

class Solution(object):
    def __init__(self):
        self.min_depth = sys.maxint

    def minDepth(self, root):
        if not root:
            return 0
        self.DFS(1, root)
        return self.min_depth
        
    def DFS(self, depth, root):
        if not root.left and not root.right:
            if depth < self.min_depth:
                self.min_depth = depth
        if root.left:
            self.DFS(depth + 1, root.left)
        if root.right:
            self.DFS(depth + 1, root.right)

2.6 二叉树的最大深度

#Leetcode 104
(1)DFS
*时间复杂度O(N)

class Solution(object):
    def __init__(self):
        self.max_depth = 0

    def maxDepth(self, root):
        if not root:
            return 0
        self.DFS(1, root)
        return self.max_depth

    def DFS(self, depth, root):
        if depth > self.max_depth:
            self.max_depth = depth
        if root.left:
            self.DFS(depth + 1, root.left)
        if root.right:
            self.DFS(depth + 1, root.right)

(2)BFS
*时间复杂度O(N)

class Solution(object):
    def __init__(self):
        self.max_depth = 0

    def maxDepth(self, root):
        if not root:
            return 0
        self.BFS(root)
        return self.max_depth

    def BFS(self, root):
        queue = [root]
        while queue:
            size = len(queue)
            self.max_depth += 1
            for _ in range(size):
                cur_node = queue.pop(0)
                if cur_node.left:
                    queue.append(cur_node.left)
                if cur_node.right:
                    queue.append(cur_node.right)

2.7 括号生成

#Leetcode 22 括号生成
(1)递归

*时间复杂度O(2^N)

(2)递归基础上剪枝优化
*时间复杂度O(2^N)

# coding = utf-8

class Solution(object):
    def __init__(self):
        self.res = []

    def fun(self, left, right, n, s):
        if left==0 and right==0:
            self.res.append(s)
            return
        if left>0:
            self.fun(left - 1, right, n, s + '(')
        if right>0 and right>left:
            self.fun(left, right - 1, n, s + ')')

    def generateParenthesis(self, n):
        """
        :type n: int
        :rtype: List[str]
        """
        s = ''
        left = n
        right = n
        self.fun(left, right, n, s)
        return self.res


if __name__=="__main__":
    s = Solution()
    print(s.generateParenthesis(3))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值