概念与分析
首先明确一个概念,二叉搜索树/二叉排序树的特点是:
二叉树的任意节点T
,都满足T.left.val < T.val && T.right.val > T.val
那么通过这一特点就有一个性质:二叉排序树/二叉搜索树 的
中序遍历
结果是递增序列
那么最简单的方法就是将树遍历一遍,然后存到数组A中,返回A[k-1]即可。
这种方法的时间效率,空间效率都是O(N) (其中N表示树中有多少个节点,且不考虑递归所带来的空间消耗)
那么我们可不可以考虑在递归的过程中保存一个计数器,当计数器值为k时,即为找到?
答案是可以的,我们要仔细思考清楚。
代码实现
int index = 0; //计数器
TreeNode KthNode(TreeNode root, int k) {
if(root == null){
return null;
}
//中序遍历寻找第k个
TreeNode node = KthNode(root.left,k);
if(node != null) {
return node;
}
index ++;
if(index == k) {
return root;
}
return KthNode(root.right,k);
}
定义函数KthNode为TreeNode KthNode(TreeNode root, int k)
,表示以root为根的二叉搜索树中,查找到第k小的节点,如果存在则返回此节点,不存在则返回NULL。
那么我们的思路就是:
先找root左子树,看是否存在第k小的节点,如果存在,那么直接返回左子树的第k小节点即可。否则进入第2步
如果左子树不存在第k小的节点,那么我们就看root节点是否就是第k个节点,如果是,则返回。否则进入第3部
直接求右子树是否存在第k小的节点
那么计数器怎么计数的呢?这个是关键!!
我们可以先考虑少量数据的情况。对于只含有3个节点的树,应该是每当遍历一个节点后,计数器就加1。
如下图所示:先序遍历到2,进入步骤1,找左子树,发现左子树为空,直接返回NULL;那么进入第2步,判断当前节点是否是第k个节点,显然当前节点是第一个节点,所以在第1,2步骤之间我们需要将计数器+1
,然后第2步判断2是否为第k个节点,如此下去,如上面所列的代码一样。
1
↙ ↘
2 3
更多
总结:主要是理解递归的流程,计数器到底该怎么变化,在何时变化,以及递归的流程安排。
上面我们提到的是求第k小的节点,那么当我们求第k大的节点
时,该怎么做呢?同样,我们可以按找这样的方式遍历二叉搜索树:先遍历又子树,再遍历当前节点,再遍历左子树;这样得到的结果为一个递减的序列,那么现在的问题就是找到这个序列的第K个元素,问题与上面一样了,代码实现只需稍作修改即可
。
版权声明:本文为qq_37206105原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。