题目描述
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4。
题目给出的是该二叉树的层序遍历结果。实际如图
可以看到,4是按大小排序时,第3个节点。如果K=3,即4为所求的值。而对应大小排序的就是中序遍历,中序遍历结果是{2,3,4,5,6,7,8},所以本题核心需要使用到中序遍历。然后对中序遍历的结果中,取第K个元素即可。这里可以使用数字或者集合存储遍历结果,然后取第k个,但是会产生额外的空间复杂度,当然也可以使用一个变量记录遍历的节点数,当遍历到K个节点时即为所求。
写法1:
使用数组存储,代码看起来非常的清晰。这个代码还有优化空间,因为完成了所有的遍历,事实上可以在遍历到K时,让遍历退出。
import java.util.ArrayList;
public class Solution {
ArrayList<TreeNode> list = new ArrayList<>();
TreeNode KthNode(TreeNode pRoot, int k) {
OrderTraversal(pRoot);
if(k<1 || list.size()<k)
return null;
return list.get(k-1);
}
// 中序遍历
public void OrderTraversal(TreeNode node) {
if(node != null) {
OrderTraversal(node.left);
list.add(node);
OrderTraversal(node.right);
}
}
}
//优化:传入参数K,并在每次遍历前都判断下k是否符合要求。
// public void OrderTraversal(TreeNode node,int k) {
// if(node != null) {
// if ( list.size() >= k ) //提前退出
// return ;
// OrderTraversal(node.left,k);
// list.add(node);
// OrderTraversal(node.right,k);
// }
// }写法2:
使用递归。
public class Solution {
int index=0;//记录当前遍历的节点数量
TreeNode KthNode(TreeNode pRoot, int k) {
TreeNode pNode = null;
if(pRoot==null || k<=0)//这里就进行了根节点为null的判断
return pNode;
pNode = getKthNode(pRoot,k);
return pNode;
}
public TreeNode getKthNode(TreeNode pRoot, int k){
TreeNode node = null;
if(pRoot.left != null)
node = getKthNode(pRoot.left,k);
//pRoot的某个子节点为null时进入下面代码
index++;
if(k == index)
node = pRoot; //满足条件就将pRoot赋值给node
//当node赋值时已经找到时,不需要再遍历了,赋值后就不为null,所以要加上这个判断条件
//写node == null或者k<index都是可以的。
if(node == null && pRoot.right!=null)
node = getKthNode(pRoot.right,k);
return node;
}
}写法3:
使用栈。
import java.util.Stack;
public class Solution {
TreeNode KthNode(TreeNode pRoot, int k)
{
int count = 0;
if(pRoot == null || k <= 0){
return null;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode node = pRoot;
//中序遍历
while(!stack.isEmpty() || node != null){
if(node != null){
stack.push(node); //当前节点不为null,应该寻找左子节点,准备让左子节点入栈
node = node.left;
}else{
node = stack.pop();//当前节点null则弹出栈内元素,相当于按顺序输出最小值。
count++;//弹出时,才应该计数
if(count == k){ //相等时就返回
return node;
}
node = node.right;//左边遍历完,还没到K,就得找右子节点
}
}
return null;
}
}


京公网安备 11010502036488号