I found BitVector another way of solving this problem.
Populating the BitVector requires O(n) time and finding an the k'th smallest element requires approximately O(k) time. Therefore the total complexity will be O(n).
Space complexity might be different according to each scenario. In my scenario, the list can contain an unsorted set of positive integers starting from 1 to 2147483647 (java.lang.Integer.MAX_VALUE) (2147483647/32 * 4 / 1024 / 1024 =~ 255 MB).
Here is my implementation in Java:
int findKthSmallestInUnsortedList(List<Integer> list, int k) {
// Step 1: Populate (read) data from list to the bit-vector in O(n) time
int[] bitVector = new int[Integer.MAX_VALUE/32]; //4 bytes chunks (int): 32 bits
for(Integer num : list) {
int chunkNum = num / 32;
int indexInChunk = num % 32;
bitVector[chunkNum] |= (1 << indexInChunk);
}
// Step 2: Find the k'th '1' starting from the first chunk in O(k) time
int count = 0;
for (int i = 0; i < bitVector.length; i++) {
int bitCount = 0;
while(bitVector[i] != 0) {
if ((bitVector[i] & 1) != 0) {
count++;
}
if (count == k) {
return i * 32 + bitCount;
}
bitCount++;
bitVector[i] >>= 1;
}
}
return -1; // not found
}
For those who are not familiar with BitVector, here is an example:
Imagine number 4 is in the list. Therefore we set the 4th bit in the first chunk to 1:
00000000 00000000 00000000 00001000
If 33 is read, according to the above implementation, we go to the second chunk and set the first bit to one and so on.
Finally, we keep counting k '1's starting from the beginning of the BitVector. When k'th 1 is found, we multiply the chunk number of that 1 with 32 and add the location of this 1 in that chunk (i * 32 + bitCount).