目录
一、概述
该博客结合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))