一、 二叉搜索树定义:
二叉搜索树是一种特殊的二叉树,满足以下两个特点:
1 每个节点处的值大于等于其左子树上的值
2 每个节点处的值小于等于其右子树上的值
示例:
中序遍历二叉搜索树树可以得到这些值的升序排序。
判断二叉树是否为二叉搜索树:
1 用递归的思想判断每个节点是否满足定义的两个特点
2 中序遍历二叉树,看是否为升序
方法一:
def ValidBST(root, minv, maxv):
if root == None:
return True
if (root.val < minv or root.val > maxv):
return False
left_result = self.ValidBST(root.left, minv, root.val)
right_result = self.ValidBST(root.right, root.val, maxv)
return left_result and right_result
def isValidBST(self, root):
maxv = Inf
minv = -Inf
return self.ValidBST(root, minv, maxv)
方法二:
def inorderTraverse(self, root):
if root == None:
return [ ]
res = [ ]
res += self.inorderTraverse(root.left)
res.append(root.val)
res += self.inorderTraverse(root.right)
return res
def isValidBST(self, root):
res = self.inorderTraverse(root)
if( res != sorted(list(set(res))):
return False
return True
二、二叉搜索树的常见操作
二叉搜索树常见的操作有查找,插入和删除
1 查找操作
- 比较当前节点值和要查找的key是否相同, 若相同则找到,返回节点。
- 若key 小于当前节点值,则查找其左子树
- 若key大于当前节点值,则查找右子树
def searchBST(self, root, val):
"""
:type root: TreeNode
:type val: int
:rtype: TreeNode
"""
if(root == None):
return []
if(root.val == val):
return root
elif(val < root.val):
return self.searchBST(root.left, val)
else :
return self.searchBST(root.right, val)
2 插入操作
给定二叉搜索树,插入一个值,有多种方式实现。这里给出改动最小的一种方式。
- 根据目标value和当前节点值的关系,去查找其左子树或者右子树
- 重复步骤一直到找到一个外部节点
- 根据目标value和外部节点值之间的关系,将目标value查到外部节点的左子树或者右子树。
def insertBST(self, root, val):
if(root == None):
root = TreeNode(val)
return root
if (val < root.val):
left = root.left
if(left == None):
left = TreeNode(val)
else :
left = self.insertBST(left, val)
elif (val > root.val):
right = root.right
if(right == None):
right = TreeNode(val)
else :
right = self.insertBST(right, val)
root.left = left
root.right = right
return root
3 删除操作
删除操作要比查找和插入操作更为复杂。和插入操作类似,也有多种删除策略,这里我们介绍改动最小的那种。主要思路是替换目标value和其合适的child,然后删除child。
- If the target node has no child, we can simply remove the node.
- If the target node has one child, we can use its child to replace itself.
- If the target node has two children, replace the node with its in-order successor or predecessor node and delete that node.
图解示例:
整体思路:
1 找到替换Node, 替换
2 删除操作。
方法一: 和前驱换
def deleteNode(self, root, key):
if(root == None):
return None
if(root.val == key):
if not root.left:
right = root.right
return right
else:
left = root.left
while left.right:
left = left.right
root.val, left.val = left.val , root.val
root.left = self.deleteNode(root.left, key)
root.right = self.deleteNode(root.right, key)
return root
方法二: 和后继换
def deleteNode(self, root, val):
if (root == None):
return None
if (root.val == val):
if not root.right :
left = root.left
return left
else :
right = root.right
while right.left:
right = right.left
root.val , right.val = right.val, root.val
root.left = self.deleteNode(root.left, val)
root.right = self.deleteNode(root.right, val)
return root
三、 总结
** 二叉搜索树的优势是, 所有操作(查找、插入、删除)都可以在o(h)时间复杂度内完成。通常, 如果需要按序存储一些数据,并且需要同时执行多个操作(查找、插入、删除),那么BST是一个不错的选择。**
应用:
查找数据流中第k大的数字
解题方法:小根堆
Python的堆是小根堆,不需要对其进行转换,我们想一想,如果一个堆的大小是k的话,那么最小的数字就在其最前面(即为第k大的数字),只要维护当新来的数字和最前面的这个数字比较即可。
所以我们的工作就是维护一个小根堆,这个小根堆保存的是从第K大的数字到最大的数字。堆的大小即为K。
class KthLargest:
def __init__(self, k: int, nums: List[int]):
self.k = k
self.pool = nums
self.size = len(self.pool)
heapq.heapify(self.pool)
while self.size > self.k:
heapq.heappop(self.pool)
self.size = self.size -1
def add(self, val: int) -> int:
if(self.size < self.k):
heapq.heappush(self.pool, val)
self.size += 1
elif (val > self.pool[0]):
heapq.heapreplace(self.pool, val)
return self.pool[0]
# Your KthLargest object will be instantiated and called as such:
# obj = KthLargest(k, nums)
# param_1 = obj.add(val)
Lowest Common Ancestor of a Binary Search Tree
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
maxval = max(p.val, q.val)
minval = min(p.val, q.val)
if root == None:
return None
elif(maxval > root.val and minval < root.val):
return root
elif (root.val == maxval or root.val == minval):
return root
elif (maxval < root.val):
return self.lowestCommonAncestor(root.left, p, q)
elif (minval > root.val):
return self.lowestCommonAncestor(root.right, p, q)