Given a binary search tree, write a function kthSmallest
to find the kth smallest element in it.
Note:
You may assume k is always valid, 1 ≤ k ≤ BST's total elements.
Example 1:
Input: root = [3,1,4,null,2], k = 1 3 / 1 4 2 Output: 1
Example 2:
Input: root = [5,3,6,2,4,null,null,1], k = 3 5 / 3 6 / 2 4 / 1 Output: 3
Follow up:
What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?
M1: dfs recursion + inorder traversal
time: O(n), space: O(n)
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { int cnt; int res = 0; public int kthSmallest(TreeNode root, int k) { cnt = k; inorder(root); return res; } private void inorder(TreeNode root) { if(root == null) { return; } inorder(root.left); cnt--; if(cnt == 0) { res = root.val; return; } inorder(root.right); } }
M2: binary search + dfs (optimal)
先对root的左子节点递归调用辅助函数求节点个数count,如果k <= count 说明第k小的元素在左子树里,如果k > count + 1 说明在右子树里,如果count = k + 1 说明当前节点就是第k小的元素,直接返回就行
time: O(h), space: O(h)
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public int kthSmallest(TreeNode root, int k) { if(root == null) { return 0; } int cnt = countNodes(root.left); if(k <= cnt) { return kthSmallest(root.left, k); } else if(k > cnt + 1) { return kthSmallest(root.right, k - cnt - 1); } return root.val; } public int countNodes(TreeNode node) { if(node == null) { return 0; } return 1 + countNodes(node.left) + countNodes(node.right); } }
ref: https://leetcode.com/problems/kth-smallest-element-in-a-bst/discuss/63660/3-ways-implemented-in-JAVA-(Python)%3A-Binary-Search-in-order-iterative-and-recursive