

java
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//用于计数和k作比较
int count = 0;
//用于返回最终的结果
int result = -1;
public int kthSmallest(TreeNode root, int k) {
inorder(root,k);
return result;
}
public void inorder(TreeNode node, int k){
if(node == null || count >= k){
return;
}
inorder(node.left,k);
//计数加1
count++;
if(count == k){
result = node.val;
return;
}
inorder(node.right,k);
}
}
因为左边的是最小的,我们要找的是从小到大的第k小的元素,所以只有在读取完左边的最小元素后才加1
处理逻辑:
前序遍历:一见到节点就报数,通常用于从上往下的路径搜索
中序遍历:二叉搜索树,从小到大唯一正确的报数时机
后序遍历:通常用于计算高度、深度和销毁树
进阶做法
java
//带有 size 属性
class MyTreeNode {
int val;
int size;
MyTreeNode left;
MyTreeNode right;
public MyTreeNode(int val) {
this.val = val;
this.size = 1;
}
}
class Solution {
// 接收官方的普通树,进行转换
public int kthSmallest(TreeNode root, int k) {
// 官方的普通树,转换成带 size 树
MyTreeNode myRoot = buildTree(root);
return findKth(myRoot, k);
}
// TreeNode 转换成 MyTreeNode,并计算 size
private MyTreeNode buildTree(TreeNode node) {
if (node == null) return null;
MyTreeNode myNode = new MyTreeNode(node.val);
myNode.left = buildTree(node.left);
myNode.right = buildTree(node.right);
int leftSize = (myNode.left != null) ? myNode.left.size : 0;
int rightSize = (myNode.right != null) ? myNode.right.size : 0;
myNode.size = leftSize + rightSize + 1;
return myNode;
}
//利用 size 找节点
private int findKth(MyTreeNode curr, int k) {
while (curr != null) {
// 看看左部分有多少节点
int leftSize = (curr.left != null) ? curr.left.size : 0;
if (k <= leftSize) {
// 目标一定在左边
curr = curr.left;
} else if (k == leftSize + 1) {
// 左边刚好排满,当前节点就是我们要找的
return curr.val;
} else {
// 目标在右边,减去当前节点左部分和当前节点的总数,拿着新 k 去右边找
curr = curr.right;
k = k - (leftSize + 1);
}
}
return -1;
}
}
重新定义节点结构,加入size;将原节点转换成带有size的节点,然后进行查找。