二叉搜索树与递归

二叉搜索树与递归----以LeetCode题目为例

首先,BST 的特性:

1、对于 BST 的每一个节点node,左子树节点的值都比node的值要小,右子树节点的值都比node的值大。

2、对于 BST 的每一个节点node,它的左侧子树和右侧子树都是 BST。

二叉搜索树并不算复杂,但我觉得它构建起了数据结构领域的半壁江山,直接基于 BST 的数据结构有 AVL 树,红黑树等等,拥有了自平衡性质,可以提供 logN 级别的增删查改效率;还有 B+ 树,线段树等结构都是基于 BST 的思想来设计的。

从做算法题的角度来看 BST,除了它的定义,还有一个重要的性质:BST 的中序遍历结果是有序的(升序)

也就是说,如果输入一棵 BST,以下代码可以将 BST 中每个节点的值升序打印出来:

1 void traverse(TreeNode root) {
2     if (root == null) return;
3     traverse(root.left);
4     // 中序遍历代码位置
5     print(root.val);
6     traverse(root.right);
7 }

 

 

230. 二叉搜索树中第K小的元素

 中序遍历便是递增顺序,然后k位置输出

 1 # Definition for a binary tree node.
 2 # class TreeNode:
 3 #     def __init__(self, val=0, left=None, right=None):
 4 #         self.val = val
 5 #         self.left = left
 6 #         self.right = right
 7 class Solution:
 8     def kthSmallest(self, root: TreeNode, k: int) -> int:
 9         ans=[]
10         def traverse(root):
11             if root==None:
12                 return 
13             traverse(root.left)
14             ans.append(root.val)
15             traverse(root.right)
16         traverse(root)
17         return ans[k-1]

感觉下面这种写法,复杂度应该更低呀,不知道为什么运行时间比上面还长

 

 1 # Definition for a binary tree node.
 2 # class TreeNode:
 3 #     def __init__(self, val=0, left=None, right=None):
 4 #         self.val = val
 5 #         self.left = left
 6 #         self.right = right
 7 class Solution:
 8     def kthSmallest(self, root: TreeNode, k: int) -> int:
 9         def traverse(root):
10             nonlocal ans,res
11             if root==None:
12                 return 
13             traverse(root.left)
14             ans+=1
15             if ans==k:
16                 res=root.val
17                 return 
18             traverse(root.right)
19         ans,res=0,-1
20         traverse(root)
21         return res

 

 

Leetcode 235. 二叉搜索树的最近公共祖先

 

 第一种,解题方法就是寻找p、q的路径,两个路径第一次相同时就是最近公共祖先

 1 # Definition for a binary tree node.
 2 # class TreeNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.left = None
 6 #         self.right = None
 7 
 8 class Solution:
 9     def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
10         def path(node, t):
11             p=[]
12             while node!=t:
13                 p.append(node)
14                 if t.val<node.val:
15                     node=node.left
16                 elif t.val>node.val:
17                     node=node.right
18             p.append(node)
19             return p
20 
21         p1=path(root,p)
22         p2=path(root,q)
23         ans=None
24         for u,v in zip(p1,p2):
25             if u==v:
26                 ans=u
27             else:
28                 break
29         return ans

 这种方法,需要动下脑子,参考作者sdwwld的写法,就是

如果两个节点值都小于根节点,说明他们都在根节点的左子树上,我们往左子树上找
如果两个节点值都大于根节点,说明他们都在根节点的右子树上,我们往右子树上找
如果一个节点值大于根节点,一个节点值小于根节点,说明他们他们一个在根节点的左子树上一个在根节点的右子树上,那么根节点就是他们的最近公共祖先节点。

 1 # Definition for a binary tree node.
 2 # class TreeNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.left = None
 6 #         self.right = None
 7 
 8 class Solution:
 9     def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
10         # 如果小于等于0,说明p和q位于root的两侧,直接返回即可
11         if ((root.val - p.val) * (root.val - q.val) <= 0):
12             return root
13         #否则,p和q位于root的同一侧,就继续往下找
14         if p.val<root.val:
15             return self.lowestCommonAncestor(root.left, p, q)
16         else:
17             return self.lowestCommonAncestor(root.right, p, q)

 

posted @ 2021-05-31 21:03  浅忆~  阅读(73)  评论(0编辑  收藏  举报