介绍
中序遍历:左子树 -> 中 -> 右子树
二叉搜索树:中序遍历可以得到有序的序列
递归法
1.使用函数循环递归处理
2.使用一个数组来保存 k, 保证在个个递归函数中都能看到 看的变化;每访问一个节点,这个数减一,当数组中的数为1时,即访问到了第k小的数
/*** Definition for a binary tree node.* public class TreeNode {* public int val;* public TreeNode left;* public TreeNode right;* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
public class Solution {public int KthSmallest(TreeNode root, int k) {// 辅助结构,当 k == 1 时 表示访问到 第 k个最小的元素int[] aux = new int[] { k };return Traverse(root, aux); }// 递归访问public int Traverse(TreeNode node, int[] aux) {if(node == null){// 用 -1 表示访问到终点return -1;}// 先访问左子树{var val = Traverse(node.left, aux);if(val != -1){return val;}}// 访问该节点{if(aux[0] == 1){// 结果return node.val;}aux[0]--;}// 后访问右子树{var val = Traverse(node.right, aux);if(val != -1){return val;}}// 这里是不会走到的根据题意return -1;}
}
优化:
1.使用 引用传递 k, 确保递归函数都能看到k的变换
2.每次访问右子树时,不用判断直接返回结果
/*** Definition for a binary tree node.* public class TreeNode {* public int val;* public TreeNode left;* public TreeNode right;* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
public class Solution {public int KthSmallest(TreeNode root, int k) {// 辅助结构,当 k == 1 时 表示访问到 第 k个最小的元素int aux = k;return Traverse(root, ref aux); }// 递归访问public int Traverse(TreeNode node, ref int aux) {if(node == null){// 用 -1 表示访问到终点return -1;}// 先访问左子树{var val = Traverse(node.left, ref aux);if(val != -1){return val;}}// 访问该节点{if(aux == 1){// 结果return node.val;}aux--;}// 后访问右子树// {// var val = Traverse(node.right, ref aux);// if(val != -1)// {// return val;// }// }// // 这里是不会走到的根据题意// return -1;// 一个优化,这里直接返回,如果没找到这里就返回-1return Traverse(node.right, ref aux);}
}
迭代法
1.使用数据结构Stack,模拟真实的栈处理流程
/*** Definition for a binary tree node.* public class TreeNode {* public int val;* public TreeNode left;* public TreeNode right;* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
public class Solution {public int KthSmallest(TreeNode root, int k) {// 借助 Stack 模拟栈Stack<TreeNode> s = new Stack<TreeNode>();// 先让第一个节点进栈,后面流程就处理一致了s.Push(root);// 根据题意一定存在结果// while(s.Count > 0)while(true){// 访问左子树var top = s.Peek();if(top != null){s.Push(top.left);continue;}// 将null节点弹出栈s.Pop();// 访问当前节点,这里不用判断 s的数量,根据代码可知,这里至少存在一个节点var visit = s.Pop();if(k == 1){// 第k最小元素return visit.val;}k--;// 访问右子树s.Push(visit.right);}return -1;}
}