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.
You may assume k is always valid, 1 ≤ k ≤ BST's total elements.
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?
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?
Hint:
- Try to utilize the property of a BST.
- What if you could modify the BST node's structure?
- The optimal runtime complexity is O(height of BST).
Code (Java):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | /** * 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 counter = 0 ; private boolean found = false ; private int val = Integer.MIN_VALUE; public int kthSmallest(TreeNode root, int k) { if (root == null ) { return 0 ; } kthSmallestHelper(root, k); return val; } private void kthSmallestHelper(TreeNode root, int k) { if (root == null ) { return ; } if (!found) { kthSmallestHelper(root.left, k); } counter++; if (counter == k) { found = true ; val = root.val; } if (!found) { kthSmallestHelper(root.right, k); } } } |
An O(h) solution:
If the BST node's structure can be modified. We let each node maintain the number of nodes of its left subtree. Therefore, for each node, we can compare k with the number of its subtree.
Code (Java):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | /** * 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 ; } int leftNodes = getNumberNodes(root.left); if (k == leftNodes + 1 ) { return root.val; } else if (k > leftNodes + 1 ) { return kthSmallest(root.right, k - leftNodes - 1 ); } else { return kthSmallest(root.left, k); } } private int getNumberNodes(TreeNode root) { if (root == null ) { return 0 ; } return getNumberNodes(root.left) + getNumberNodes(root.right) + 1 ; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | /** * Definition of TreeNode: * public class TreeNode { * public int val; * public TreeNode left, right; * public TreeNode(int val) { * this.val = val; * this.left = this.right = null; * } * } */ public class Solution { /** * @param root: the given BST * @param k: the given k * @return: the kth smallest element in BST */ public int kthSmallest(TreeNode root, int k) { // write your code here BSTNode bstRoot = buildBST(root); BSTNode p = bstRoot; while (p != null ) { int numLeft = p.left == null ? 0 : p.left.numNodes; int numRight = p.right == null ? 0 : p.right.numNodes; if (k == numLeft + 1 ) { return p.val; } if (k <= numLeft) { p = p.left; } else { p = p.right; k = k- numLeft - 1 ; } } return - 1 ; } private BSTNode buildBST(TreeNode root) { if (root == null ) { return null ; } BSTNode left = buildBST(root.left); BSTNode right = buildBST(root.right); int numNodes = (left == null ? 0 : left.numNodes) + (right == null ? 0 : right.numNodes) + 1 ; BSTNode bstRoot = new BSTNode(root.val, numNodes); bstRoot.left = left; bstRoot.right = right; return bstRoot; } } class BSTNode { int val; int numNodes; BSTNode left, right; public BSTNode( int val, int numNodes) { this .val = val; this .numNodes = numNodes; left = right = null ; } } |
No comments:
Post a Comment