思路:
方法一 & 二:
中序遍历BST,第K个遍历到的节点就是第K小的元素。
缺点:每次找都要遍历整个BST,需要O(N)的时间复杂度(其中N为节点个数)和维护一个栈的开销。题目给了hint:可以修改树的节点的结构使得复杂度降低到O(logN)。
java code(iterative):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int kthSmallest(TreeNode root, int k) {
if(root == null) return 0;
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode node = root;
while(node != null) {
s.push(node);
node = node.left;
}
int count = 0;
while(!s.empty() && count < k) {
node = s.peek();
s.pop();
count++;
TreeNode cur = node.right;
while(cur != null) {
s.push(cur);
cur = cur.left;
}
}
return node.val;
}
}
java code:(DFS)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
private int number = 0;
private int count = 0;
private void dfs(TreeNode cur) {
if(cur.left != null) {
dfs(cur.left);
}
count--;
if(count == 0) {
number = cur.val;
return;
}
if(cur.right != null) {
dfs(cur.right);
}
}
public int kthSmallest(TreeNode root, int k) {
count = k;
dfs(root);
return number;
}
}
方法三:
计算每个节点的左子树的节点个数:
如果左子树的节点个数 >= k :则从左子树中找;
如果左子树的节点个数 + 1== k :则当前节点就是要找的节点;
如果左子树的节点个数 + 1 < k:则从右子树中找第 k - count - 1 的节点就好;
时间复杂度:O(logN)。
java code:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
private int countNodes(TreeNode node) {
if(node == null) return 0;
return 1 + countNodes(node.left) + countNodes(node.right);
}
public int kthSmallest(TreeNode root, int k) {
int count = countNodes(root.left);
if(k <= count) {//in the bst's left side
return kthSmallest(root.left, k);
}else if(k == count + 1) {
return root.val;
}else {//k > count + 1
return kthSmallest(root.right, k - count - 1);
}
}
}