【Java】面试题54:二叉搜索树的第k大的节点

题目:给定一棵二叉搜索树,请找出其中第k大的节点。

例如,下图中的二叉搜索树中,按节点数值大小顺序第三个节点的值 是4.

【Java】面试题54:二叉搜索树的第k大的节点
算法分析:
如果按照中序遍历的顺序遍历一棵二叉搜索树,遍历序列的数值是递增排序的。上图中的二叉搜索树的中序遍历序列为{2,3,4,5,6,7,8},因此,只需要用中序遍历算法遍历一棵二叉搜索树,就很容易找出它的第k大结点。

方法一:递归中序遍历

package jianZhiOffer;
/*
 * 面试题54:二叉搜索树的第k个大节点
 * 题目:给定一棵二叉搜索树,请找出其中第k大的节点。
 */
public class Demo54 {
	class BinaryTreeNode{
		int val;
		BinaryTreeNode left;
		BinaryTreeNode right;
		public BinaryTreeNode(int val) {
			this.val = val;
		}
		
	}
	public static void main(String[] args) {
		Demo54 demo = new Demo54();
		BinaryTreeNode root = demo.new BinaryTreeNode(5);
		BinaryTreeNode a = demo.new BinaryTreeNode(3);
		BinaryTreeNode b = demo.new BinaryTreeNode(7);
		BinaryTreeNode c = demo.new BinaryTreeNode(2);
		BinaryTreeNode d = demo.new BinaryTreeNode(4);
		BinaryTreeNode e = demo.new BinaryTreeNode(6);
		BinaryTreeNode f = demo.new BinaryTreeNode(8);
		
		root.left = a;
		root.right = b;
		a.left = c;
		a.right = d;
		b.left = e;
		b.right = f;
		
		BinaryTreeNode k = KthNode(root,3);
		System.out.println(k.val);
	}
	
	static int index=0;
	
	static BinaryTreeNode KthNode(BinaryTreeNode pRoot,int k) {
		if(pRoot==null || k<=0)
			return null;
		return getKthNode(pRoot,k);
	}
	
	private static BinaryTreeNode getKthNode(BinaryTreeNode pRoot,int k) {
		BinaryTreeNode KthNode = null;
		if(pRoot.left != null)//如果该节点有左孩子,就一直递归到左叶子节点
			KthNode = getKthNode(pRoot.left,k);
		if(KthNode==null) {
			index++;  //中序遍历的计数
			if(k==index)
				KthNode = pRoot; 
		}
		
		if(KthNode==null && pRoot.right!=null)
			//如果该节点有右孩子,就递归到右孩子
			KthNode = getKthNode(pRoot.right,k);
		
		return KthNode;
		
	}
}

需要注意的就是递归的流程和条件。

方法二:非递归中序遍历,用栈来实现

TreeNode KthNode(BinaryTreeNode root, int k){
        if(root==null||k==0) return null;
        int count=0;
        Stack<BinaryTreeNode> stack=new Stack<>();
        while(root!=null||!stack.isEmpty()){
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root=stack.pop();
            count++;
            if(count==k) return root;
            root=root.right;
        }
        return null;
    }