labuladong 二叉搜索树操作集锦
- 二叉树
- 二叉树算法设计的总路线:把当前节点要做的事做好,其他的交给递归框架,不用当前节点操心。 (可以理解成递归方法的应用)
- 明确递归结束的条件 (已经到了叶子节点)
- 把root该做的事情做完, 然后左右子节点递归调用该方法
- 如果当前节点会对下面的子节点有整体影响,可以通过辅助函数增长参数列表,借助参数传递信息。
- 二叉树算法设计的总路线:把当前节点要做的事做好,其他的交给递归框架,不用当前节点操心。 (可以理解成递归方法的应用)
void traverse(TreeNode root) {
// root 需要做什么?在这做。
// 其他的不用 root 操心,抛给框架
traverse(root.left);
traverse(root.right);
}
- 二叉搜索树
- 定义:任意节点的值要大于等于左子树所有节点的值,且要小于等于右子树的所有节点的值。
- 因此,中序遍历二叉搜索树后,可以得到递增数组。
void BST(TreeNode root, int target) {
if (root.val == target)
// 找到目标,做点什么
if (root.val < target)
BST(root.right, target);
if (root.val > target)
BST(root.left, target);
}
100. 相同的树
- 函数内先判断两个root节点是否相等,然后递归调用该函数,判断左右子节点是否相等
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def isSameTree(self, p, q):
"""
:type p: TreeNode
:type q: TreeNode
:rtype: bool
"""
if p==None and q ==None: return True # 都为空节点
if p==None or q ==None: return False # 其中一个为空节点
if p.val!=q.val:return False # 值不相等
# 调用递归,判断左右子树是否都满足isSameTree
return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
面试题 04.05. 合法二叉搜索树
方法1:利用携带的最大最小值进行判断
-
root 需要做的不只是和左右子节点比较,而是要和整个左子树和右子树所有节点比较
-
使用辅助函数,增加函数参数列表,在参数中携带额外信息(当前节点需要比较的最小值和最大值)
- 直接赋予最小值
-float("inf")
、最大值float("inf")
,在递归的过程中修改最值(自顶向下的过程中,右子树的最小值从-float("inf")
逐渐增大,左子树的最大值从float("inf")
逐渐减小)
- 直接赋予最小值
以该不合法的二叉搜索树树为例:
- 遍历到15 时,15与
[10, float("inf")]
比较,结果是True(此时最小值为10)- 对于15的左子树,它应该在[10,15] 范围内,但现在是6,结果为False
# 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 isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
def valid(root,mi,ma):
if root==None: return True
if root.val<=mi: return False
if root.val>=ma: return False
return valid(root.left, mi , root.val) and valid(root.right, root.val, ma)
return valid(root, -float("inf"), float("inf"))
方法2:中序遍历二叉搜索树后,判断其是否为没有重复元素的递增数组
- 最后的
return nodes == sorted(set(nodes))
, 要先set,再 sorted,这样返回的是列表形式,即判断列表是否等于列表(若先sorted,再set,返回的是一个集合,即判断列表是否等于集合,出现错误)。
# 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 isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
nodes=[]
def inOrder(root): # 中序遍历后,判断其是否递增
if not root: return True
inOrder(root.left)
nodes.append(root.val)
inOrder(root.right)
return nodes
inOrder(root)
return nodes == sorted(set(nodes))
700. 二叉搜索树中的搜索
# 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 searchBST(self, root, val):
"""
:type root: TreeNode
:type val: int
:rtype: TreeNode
"""
if not root: return None
if root.val==val: return root
if root.val>val:
return seatchBST(self,root.left,val)
if root.val<val:
return searchBST(self,root.right,val)
701.二叉搜索树的插入操作
对数据结构的操作无非遍历 + 访问,遍历就是“找”,访问就是“改”。具体到这个问题,插入一个数,就是先找到插入位置,然后进行插入操作。
上一个问题,我们总结了 BST 中的遍历框架,就是“找”的问题。直接套框架,加上“改”的操作即可。一旦涉及“改”,函数就要返回 TreeNode 类型,并且对递归调用的返回值进行接收。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def insertIntoBST(self, root, val):
"""
:type root: TreeNode
:type val: int
:rtype: TreeNode
"""
if not root:
root=TreeNode(val)
return root
if val>root.val:
root.right=self.insertIntoBST(root.right,val)
elif val< root.val:
root.left=self.insertIntoBST(root.left,val)
return root
450. 删除二叉搜索树中的节点
# 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 deleteNode(self, root, key):
"""
:type root: TreeNode
:type key: int
:rtype: TreeNode
"""
# 若无根节点,直接返回
if not root:return None
# 若找到目标值
if root.val==key:
# 处理无子节点/只有一个子节点的情况
if root.left==None: return root.right
if root.right==None: return root.left
# 找到右子树的最左(小)节点,并替换
minNode=self.getMin(root.right)
root.val=minNode.val
# 转而删除最小节点
root.right=self.deleteNode(root.right,minNode.val)
# 二叉搜索树
elif root.val>key:
root.left=self.deleteNode(root.left,key)
else:
root.right=self.deleteNode(root.right,key)
return root
def getMin(self,root): # 最小值一定在左叶子节点处
while root.left!=None:
root=root.left
return root
二叉树的遍历
只需要改变遍历的顺序即可
前序遍历
class Solution(object):
def preorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
res = []
def helper(root):
if not root:return
res.append(root.val)
helper(root.left)
helper(root.right)
helper(root)
return res
# 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 inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
res=[]
def helper(root):
if not root: return
helper(root.left)
res.append(root.val)
helper(root.right)
helper(root)
return res
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
res = []
def helper(root):
if not root:
return
helper(root.left)
helper(root.right)
res.append(root.val)
helper(root)
return res
层序遍历
- 队列中存储当前层的节点,然后利用先进先出特性将结果保存
# 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 levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root: return []
from collections import deque
res=[]
queue=deque()
queue.append(root)
while queue:
node=queue.popleft()
res.append(node.val)
if node.left:queue.append(node.left)
if node.right:queue.append(node.right)
return res
# 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 levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root: return []
res = []
queue = collections.deque()
queue.append(root)
while queue:
tmp = []
for i in range(len(queue)):
node = queue.popleft()
tmp.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
res.append(tmp)
return res