二叉搜索树与递归
二叉搜索树与递归----以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)