leetcode刷题记录:二叉搜索树
https://labuladong.online/algo/data-structure/bst-part1/
定义
- 对于任意一个节点node,左子树node小,右子树比node大
- 左右子树都是bst
特性:中序遍历结果有序
1. 中序遍历
寻找第k小 https://leetcode.cn/problems/kth-smallest-element-in-a-bst/
class Solution(object):
def kthSmallest(self, root, k):
"""
:type root: TreeNode
:type k: int
:rtype: int
"""
cur = root
st = []
idx = 0
res = []
while cur or st:
if cur:
st.append(cur)
cur = cur.left
else:
cur = st.pop()
res.append(cur.val)
idx += 1
if idx == k:
return cur.val
cur = cur.right
BST转化为累加树
递归法反向中序遍(右中左),用一个全局变量记录sum
class Solution(object):
def convertBST(self, root):
"""
:type root: TreeNode
:rtype: TreeNode
"""
def dfs(root):
if not root:
return
dfs(root.right)
root.val += self.total
self.total = root.val
dfs(root.left)
self.total = 0
dfs(root)
return root
2. BST基本操作:判断合法性,增删查
判断BST的合法性
https://leetcode.cn/problems/validate-binary-search-tree/
迭代法中序遍历
class Solution(object):
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
cur = root
st = []
prev = None
while st or cur:
while cur:
st.append(cur)
cur = cur.left
cur = st.pop()
# 注意,下面的if条件一定是if prev is not None, 而不是 if prev. 因为prev=0的时候,if prev = False
if prev is not None and prev >= cur.val:
return False
prev = cur.val
cur = cur.right
return True
寻找一个节点
https://leetcode.cn/problems/search-in-a-binary-search-tree/
二分搜索,很简单
class Solution(object):
def searchBST(self, root, val):
"""
:type root: TreeNode
:type val: int
:rtype: TreeNode
"""
if not root:
return root
if root.val == val:
return root
elif root.val < val:
return self.searchBST(root.right, val)
else:
return self.searchBST(root.left, val)
在BST中插入一个数
和查找一个数基本一样,稍微修改一下二分搜索的逻辑,接收递归的返回值
class Solution(object):
def insertIntoBST(self, root, val):
"""
:type root: TreeNode
:type val: int
:rtype: TreeNode
"""
if not root:
return TreeNode(val)
if root.val < val:
root.right = self.insertIntoBST(root.right, val)
elif root.val > val:
root.left = self.insertIntoBST(root.left,val)
return root
在BST中删除一个数
分情况讨论。
class Solution(object):
def deleteNode(self, root, key):
"""
:type root: TreeNode
:type key: int
:rtype: TreeNode
"""
def findMin(root):
while root and root.left:
root = root.left
return root
if not root:
return root
if root.val > key:
root.left = self.deleteNode(root.left, key)
elif root.val < key:
root.right = self.deleteNode(root.right, key)
else:
if not root.left:
root = root.right
elif not root.right:
root = root.left
else:
# 注意传参,root.right 不是root
minNode = findMin(root.right)
# 注意传参,minNode.val 不是minNode,容易出错
root.right = self.deleteNode(root.right, minNode.val)
minNode.left = root.left
minNode.right = root.right
root = minNode
return root
3. 构造
不同的二叉搜索树
穷举,用备忘录来消重。思路上非常简单,比dp容易想。
cuunt函数要传两个参数,缺点是memo是二维的,空间复杂度是O(n2)
class Solution(object):
def numTrees(self, n):
"""
:type n: int
:rtype: int
"""
def count(lo, hi):
if lo > hi:
return 1
if self.memo[lo][hi] > 0:
res = self.memo[lo][hi]
else:
res = 0
for i in range(lo, hi+1):
res += count(lo, i-1) * count(i+1, hi)
self.memo[lo][hi] = res
return res
self.memo = [[-1 for _ in range(n+1)] for _ in range(n+1)]
return count(1, n)
不同的二叉搜索树 II
和I类似
class Solution(object):
def generateTrees(self, n):
"""
:type n: int
:rtype: List[TreeNode]
"""
def dfs(lo, hi):
if lo > hi:
return [None]
res = []
for i in range(lo, hi+1):
leftTrees = dfs(lo, i-1)
rightTrees = dfs(i+1, hi)
for left in leftTrees:
for right in rightTrees:
root = TreeNode(i)
root.left = left
root.right = right
res.append(root)
return res
if n == 0:
return []
return dfs(1, n)