查找最小的k 个元素

这是微软面试100题。

关于这的讲解有很多。

最经典的属于July的一篇博文:寻找最小K个数 http://blog.csdn.net/v_JULY_v/article/details/6370650

下面有另一篇更浅显易懂的文章:作者robbin先生, http://www.cnblogs.com/Ribbon/p/3629676.html

下面是全文:

紧接着上一篇微软编程面试100题,这次想解决的是查找最小的K个元素,题目是:输入n 个整数,输出其中最小的k 个。例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。

看到题目的时候我第一反应,这题很简单,使用任何方式的排序将数列按顺序存储,之后遍历需要的k个元素即可,于是自己动手很容易就完成了,但是后来在网络上发现很多人对这题的解决方式是用小根堆(MinHeap)或者大根堆(MaxHeap),这才意识到,其实出题人是醉翁之意不在酒,在乎复杂度的考虑也。

先写用排序的方式完成题目的方式吧,不仅简单,不需要费太多脑子,重要的是,正好趁这时候复习下排序,这里用快速排序完成:

 1 public static void Quick_Sort(int[] sort, int left, int right)

 2 {

 3     int mid = sort[(left + right) / 2];

 4     int i = left;

 5     int j = right;

 6     do

 7     {

 8         while (sort[i] < mid && i < right) i++;

 9         while (sort[j] > mid && j > left) j--;

10         if (i <= j)

11         {

12             int temp = sort[i];

13             sort[i] = sort[j];

14             sort[j] = temp;

15             i++;

16             j--;

17         }

18  

19     } while (i <= j);

20  

21     if (j > left) Quick_Sort(sort, left, j);

22     if (i < right) Quick_Sort(sort, i, right);

23 }  

然后定义一个MinKMethod的方法来获取所需元素:

 1 public static void MinKMethod(int[] sort, int k)

 2 {

 3     Quick_Sort(sort, 0, sort.Length - 1);

 4     if (k > sort.Length)

 5     {

 6         for (int j = 0; j < sort.Length; j++)

 7         {

 8             Console.Write(sort[j] + " ");

 9         }

10         Console.WriteLine();

11     }

12     if (k <= 0)

13     {

14         Console.WriteLine("Nothing Output");

15     }

16     if (k > 0 && k < sort.Length)

17     {

18         for (int j = 0; j < k; j++)

19         {

20             Console.Write(sort[j] + " ");

21         }

22     }

23  

24 } 

这么做的话,最快需要O(NlogN)的时间进行排序,然后在O(1)的时间内将k个数取出。

接下来看看如何用堆完成这个题:

 1 public static void FindKMin(int[] sort, int k)

 2 {

 3     int[] heap = sort;

 4     int rootIndex = k / 2 - 1;

 5     while (rootIndex >= 0)

 6     {

 7         reheap(heap, rootIndex, k - 1);

 8         rootIndex--;

 9     }

10  

11     for (int i = k, len=heap.Length; i < len; i++)

12     {

13         if (heap[i]<heap[0])

14         {

15             heap[0] = heap[i];

16             reheap(heap, 0, k - 1);

17         }

18     }

19  

20     Console.WriteLine("The {0} min element =",k);

21     for (int i = 0; i < k; i++)

22     {

23         Console.Write(heap[i] + " ");

24     }

25 }

26  

27 private static void reheap(int[] heap, int rootIndex, int lastInddex)

28 {

29     int orphan = heap[rootIndex];

30     bool done = false;

31     int leftIndex = rootIndex * 2 + 1;

32     while (!done && leftIndex <= lastInddex)

33     {

34         int largerIndex = leftIndex;

35         if (leftIndex+1 <= lastInddex)

36         {

37             int rightIndex = leftIndex + 1;

38             if (heap[rightIndex] > heap[leftIndex])

39             {

40                 largerIndex = rightIndex;

41             }

42         }

43  

44         if (orphan < heap[largerIndex])

45         {

46             heap[rootIndex] = heap[largerIndex];

47             rootIndex = largerIndex;

48             leftIndex = rootIndex * 2 + 1;

49         }

50         else

51         {

52             done = true;

53         }

54     }

55  

56     heap[rootIndex] = orphan;

57 }

用堆解决这个问题其实思路并不难,前提是,需要对堆有一定的理解。

你可能感兴趣的:(查找)