题目:给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。
思路:这里的第k大结点就是指按从小到大顺序排列后的第k个结点。显然题目很简单,搜索二叉树按照中序遍历就是一个有序的序列,于是中序遍历这个二叉树,每次遍历一个结点记录一个计数器,当计算到count=k的结点就是所求的结点。可以使用递归或者循环来解决。使用递归时思考:如何在递归的同时记录计数器?中序遍历时,总是先处理左子树—再处理中间结点即遍历—再处理右子树,因此每次在处理中间结点时进行计数即可。递归中如何当count==k时结束全部递归的调用而不需要遍历全部的结点?
F1:当count==k时就及时return,那么在本次递归调用过程中,在本层就不需要遍历root的右子树,直接返回到上一层,在上一层还是要判断count==k,并且如果不满足还是要执行this.process(root.right,k)来遍历右子树,即添加return后只是在本层中可以不用遍历右子树,在其他层还是要遍历右子树的,即还是要执行return后的代码。例如上面的二叉树中,如果k=2,那么要查找的结点时③,于是根据下面的程序,在遍历到结点③时就return,于是结点③的右子树不会遍历,即结点④不会遍历,但是之后的层次的右子树还是会遍历的,例如⑤的右子树都会遍历,此时遍历结束后的count=6,即不用遍历1个结点;如果k=4,那么结点⑤是要查找的结点,当遍历到结点⑤时就return,于是结点⑤的右子树都不会遍历,此时遍历完成后后count=4,即不用遍历3个结点。
//给定一棵搜索二叉树找第k大结点,中序遍历,递归,遍历的同时进行计数
publicclass Solution {
TreeNode res;
int count=0;
TreeNode KthNode(TreeNode pRoot, int k){
//特殊输入
if(pRoot==null) return null;
//调用递归方法解决问题
this.process(pRoot,k);
return res;
}
//递归方法:找出二叉树中序遍历中的第k个值
private void process(TreeNode root,int k){
//边界条件:遍历到最后的空节点时显然说明找不到,于是返回null
if(root==null) return;
//①先遍历左边的子树
this.process(root.left,k);
//②遍历当前结点,同时计数
if(++count==k){
res=root;
//F1:这里可以不加return,但是加上return表示一旦找到结点之后的右子树就不用再遍历了
return;
}
//③遍历右子树
this.process(root.right,k);
}
}