题目描述
- 给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。
- 地址:牛客链接
问题分析
- 因为是二叉搜索树,所以对它进行中序遍历得到的结果便是一个有序数列,从而很好找到第K个节点。
- 但对于这题,我们只要找到第K个节点便可以停止,无需遍历所有节点,具体有以下两种做法:
- 递归法:只需在原中序遍历递归版的基础上,在打印字符的那一处,改为count++,并确定当前count是否已经达到K即可。
TreeNode KthNode(TreeNode pRoot, int[] count, int k)
表示在已经查找到了count[0]个节点之后,查找第K个节点,具体细节见实现
- 非递归法,用栈来实现中序遍历的非递归,同样在打印字符的那一处,改为count++,并确定当前count是否已经达到K即可。具体见实现
经验教训
- 二叉搜索树中序遍历的性质
- 二叉树三大遍历的递归写法,以及非递归写法
代码实现
TreeNode KthNode(TreeNode pRoot, int k) {
if (pRoot == null || k <= 0) {
return null;
}
int[] count = new int[1];
return KthNode(pRoot, count, k);
}
TreeNode KthNode(TreeNode pRoot, int[] count, int k) {
if (pRoot == null) {
return null;
}
TreeNode leftRes = KthNode(pRoot.left, count, k);
if (leftRes != null) {
return leftRes;
}
count[0]++;
if (count[0] == k) {
return pRoot;
}
return KthNode(pRoot.right, count, k);
}
TreeNode KthNode(TreeNode pRoot, int k) {
if (pRoot == null || k <= 0) {
return null;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode curNode = pRoot;
int count = 0;
while (curNode != null || ! stack.isEmpty()) {
while (curNode != null) {
stack.push(curNode);
curNode = curNode.left;
}
curNode = stack.pop();
if (++count == k) {
return curNode;
}
curNode = curNode.right;
}
return null;
}