Kth Smallest Number (hard)
Problem Statement #
Given an unsorted array of numbers, find Kth smallest number in it.
Please note that it is the Kth smallest number in the sorted order, not the Kth distinct element.
Example 1:
Input: [1, 5, 12, 2, 11, 5], K = 3
Output: 5
Explanation: The 3rd smallest number is '5', as the first two smaller numbers are [1, 2].
Example 2:
Input: [1, 5, 12, 2, 11, 5], K = 4
Output: 5
Explanation: The 4th smallest number is '5', as the first three smaller numbers are
[1, 2, 5].
Example 3:
Input: [5, 12, 11, -1, 12], K = 3
Output: 11
Explanation: The 3rd smallest number is '11', as the first two small numbers are [5, -1].
Try it yourself #
Try solving this question here:
import java.util.*;class KthSmallestNumber {public static int findKthSmallestNumber(int[] nums, int k) {// TODO: Write your code herereturn -1;}public static void main(String[] args) {int result = KthSmallestNumber.findKthSmallestNumber(new int[] { 1, 5, 12, 2, 11, 5 }, 3);System.out.println("Kth smallest number is: " + result);// since there are two 5s in the input array, our 3rd and 4th smallest numbers should be a '5'result = KthSmallestNumber.findKthSmallestNumber(new int[] { 1, 5, 12, 2, 11, 5 }, 4);System.out.println("Kth smallest number is: " + result);result = KthSmallestNumber.findKthSmallestNumber(new int[] { 5, 12, 11, -1, 12 }, 3);System.out.println("Kth smallest number is: " + result);}}
This is a well-known problem and there are multiple solutions available to solve this. A few other similar problems are:
- Find the Kth largest number in an unsorted array.
- Find the median of an unsorted array.
- Find the ‘K’ smallest or largest numbers in an unsorted array.
Let’s discuss different algorithms to solve this problem and understand their time and space complexity. Similar solutions can be devised for the above-mentioned three problems.
1. Brute-force #
The simplest brute-force algorithm will be to find the Kth smallest number in a step by step fashion. This means that, first, we will find the smallest element, then 2nd smallest, then 3rd smallest and so on, until we have found the Kth smallest element. Here is what the algorithm will look like:
class KthSmallestNumber {public static int findKthSmallestNumber(int[] nums, int k) {int previousSmallestNum = Integer.MIN_VALUE;int previousSmallestIndex = -1;int currentSmallestNum = Integer.MAX_VALUE;int currentSmallestIndex = -1;for (int i = 0; i < k; i++) {for (int j = 0; j < nums.length; j++) {if (nums[j] > previousSmallestNum && nums[j] < currentSmallestNum) {// found the next smallest numbercurrentSmallestNum = nums[j];currentSmallestIndex = j;} else if (nums[j] == previousSmallestNum && j > previousSmallestIndex) {// found a number which is equal to the previous smallest number; since numbers can repeat,// we will consider 'nums[j]' only if it has a different index than previous smallestcurrentSmallestNum = nums[j];currentSmallestIndex = j;break; // break here as we have found our definitive next smallest number}}// current smallest number becomes previous smallest number for the next iterationpreviousSmallestNum = currentSmallestNum;previousSmallestIndex = currentSmallestIndex;currentSmallestNum = Integer.MAX_VALUE;}return previousSmallestNum;}public static void main(String[] args) {int result = KthSmallestNumber.findKthSmallestNumber(new int[] { 1, 5, 12, 2, 11, 5 }, 3);System.out.println("Kth smallest number is: " + result);// since there are two 5s in the input array, our 3rd and 4th smallest numbers should be a '5'result = KthSmallestNumber.findKthSmallestNumber(new int[] { 1, 5, 12, 2, 11, 5 }, 4);System.out.println("Kth smallest number is: " + result);result = KthSmallestNumber.findKthSmallestNumber(new int[] { 5, 12, 11, -1, 12 }, 3);System.out.println("Kth smallest number is: " + result);}}
Time & Space Complexity
The time complexity of the above algorithm will be . The algorithm runs in constant space .
2. Brute-force using Sorting
We can use an in-place sort like a HeapSort to sort the input array to get the Kth smallest number. Following is the code for this solution:
import java.util.*;class KthSmallestNumber {public static int findKthSmallestNumber(int[] nums, int k) {Arrays.sort(nums);return nums[k - 1];}public static void main(String[] args) {int result = KthSmallestNumber.findKthSmallestNumber(new int[] { 1, 5, 12, 2, 11, 5 }, 3);System.out.println("Kth smallest number is: " + result);// since there are two 5s in the input array, our 3rd and 4th smallest numbers should be a '5'result = KthSmallestNumber.findKthSmallestNumber(new int[] { 1, 5, 12, 2, 11, 5 }, 4);System.out.println("Kth smallest number is: " + result);result = KthSmallestNumber.findKthSmallestNumber(new int[] { 5, 12, 11, -1, 12 }, 3);System.out.println("Kth smallest number is: " + result);}}
Time & Space Complexity
Sorting will take and if we are not using an in-place sorting algorithm, we will need space.
3. Using Max-Heap
As discussed in Kth Smallest Number, we can iterate the array and use a Max Heap to keep track of ‘K’ smallest number. In the end, the root of the heap will have the Kth smallest number.
Here is what this algorithm will look like:
import java.util.*;class KthSmallestNumber {public static int findKthSmallestNumber(int[] nums, int k) {PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>((n1, n2) -> n2 - n1);// put first k numbers in the max heapfor (int i = 0; i < k; i++)maxHeap.add(nums[i]);// go through the remaining numbers of the array, if the number from the array is smaller than the// top (biggest) number of the heap, remove the top number from heap and add the number from arrayfor (int i = k; i < nums.length; i++) {if (nums[i] < maxHeap.peek()) {maxHeap.poll();maxHeap.add(nums[i]);}}// the root of the heap has the Kth smallest numberreturn maxHeap.peek();}public static void main(String[] args) {int result = KthSmallestNumber.findKthSmallestNumber(new int[] { 1, 5, 12, 2, 11, 5 }, 3);System.out.println("Kth smallest number is: " + result);// since there are two 5s in the input array, our 3rd and 4th smallest numbers should be a '5'result = KthSmallestNumber.findKthSmallestNumber(new int[] { 1, 5, 12, 2, 11, 5 }, 4);System.out.println("Kth smallest number is: " + result);result = KthSmallestNumber.findKthSmallestNumber(new int[] { 5, 12, 11, -1, 12 }, 3);System.out.println("Kth smallest number is: " + result); }}
Time & Space Complexity
The time complexity of the above algorithm is ...