Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm to find k smallest numbers in array of n items

I'm trying to write an algorithm which can print the k smallest numbers in an n-size-array in O(n) time, but I cannot reduce the time complexity to n. How can I do this?

like image 983
Jessica Avatar asked Mar 21 '11 16:03

Jessica


People also ask

How do you find the smallest number in an array?

For an array of ascending order the first element is the smallest element, you can get it by arr[0] (0 based indexing). If the array is sorted in descending order then the last element is the smallest element,you can get it by arr[sizeOfArray-1].

Which sorting algorithm is used to get the kth smallest element from the unsorted list of elements?

Method 1 (Simple Solution) A simple solution is to sort the given array using an O(N log N) sorting algorithm like Merge Sort, Heap Sort, etc, and return the element at index k-1 in the sorted array.


2 Answers

I've done this in an interview before, and one of the most elegant/efficient ways to do this is

O(n log k).  with space: O(k) (thanks, @Nzbuu) 

Basically you're going to use a max-heap of size limited to k. For each item in the array, check to see if it's smaller than the max (only O(1)). If it is, remove the max and put that in the heap (O(log k)). If its bigger, go to the next item.

Of course, the heap doesn't yield a sorted list of k items, but that can be done in O(k log k) which is easy.

Similarly, you can do the same for finding the largest k items, in which case you would use a min-heap.

like image 139
Chet Avatar answered Nov 07 '22 02:11

Chet


you will need to find the k'th smallest element using 'selection algorithm', which is O(n), and then iterate the array again and return each element which is smaller/equals it.
selection algorithm: http://en.wikipedia.org/wiki/Selection_algorithm
you will have to pay attention if you have repeats: you will need to make sure you are not returning more then k elements (it is possible if for instance you have 1,2,...,k,k,k,...)

EDIT :
the full algorithm, and returning a list, as requested: let the array be A

 1. find the k'th element in A using 'selection algorithm', let it be 'z'  2. initialize an empty list 'L'  3. initialize counter<-0  4. for each element in A:   4.1. if element < z:     4.1.1. counter<-counter + 1 ; L.add(element)  5. for each element in A:  5.1. if element == z AND count < k:    5.1.1. counter<-counter + 1 ; L.add(element)  6. return L 

note here that a 3rd iteration is required if your list might have duplicates. if it can't - it is needless, just change the condition in 4.1 to <=.
also note: L.add is inserting an element to a linked list and thus is O(1).

like image 31
amit Avatar answered Nov 07 '22 02:11

amit