查找最小的k 个元素之C#算法实现
紧接着上一篇微软编程面试100题,这次想解决的是查找最小的K个元素,题目是:输入n 个整数,输出其中最小的k 个。例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。
看到题目的时候我第一反应,这题很简单,使用任何方式的排序将数列按顺序存储,之后遍历需要的k个元素即可,于是自己动手很容易就完成了,但是后来在网络上发现很多人对这题的解决方式是用小根堆(MinHeap)或者大根堆(MaxHeap),这才意识到,其实出题人是醉翁之意不在酒,在乎复杂度的考虑也。
先写用排序的方式完成题目的方式吧,不仅简单,不需要费太多脑子,重要的是,正好趁这时候复习下排序,这里用快速排序完成:
public static void Quick_Sort(int[] sort, int left, int right) { int mid = sort[(left + right) / 2]; int i = left; int j = right; do { while (sort[i] < mid && i < right) i++; while (sort[j] > mid && j > left) j--; if (i <= j) { int temp = sort[i]; sort[i] = sort[j]; sort[j] = temp; i++; j--; } } while (i <= j); if (j > left) Quick_Sort(sort, left, j); if (i < right) Quick_Sort(sort, i, right); }
然后定义一个MinKMethod的方法来获取所需元素:
public static void MinKMethod(int[] sort, int k) { Quick_Sort(sort, 0, sort.Length - 1); if (k > sort.Length) { for (int j = 0; j < sort.Length; j++) { Console.Write(sort[j] + " "); } Console.WriteLine(); } if (k <= 0) { Console.WriteLine("Nothing Output"); } if (k > 0 && k < sort.Length) { for (int j = 0; j < k; j++) { Console.Write(sort[j] + " "); } } }
这么做的话,最快需要O(NlogN)的时间进行排序,然后在O(1)的时间内将k个数取出。
接下来看看如何用堆完成这个题:
public static void FindKMin(int[] sort, int k) { int[] heap = sort; int rootIndex = k / 2 - 1; while (rootIndex >= 0) { reheap(heap, rootIndex, k - 1); rootIndex--; } for (int i = k, len=heap.Length; i < len; i++) { if (heap[i]<heap[0]) { heap[0] = heap[i]; reheap(heap, 0, k - 1); } } Console.WriteLine("The {0} min element =",k); for (int i = 0; i < k; i++) { Console.Write(heap[i] + " "); } } private static void reheap(int[] heap, int rootIndex, int lastInddex) { int orphan = heap[rootIndex]; bool done = false; int leftIndex = rootIndex * 2 + 1; while (!done && leftIndex <= lastInddex) { int largerIndex = leftIndex; if (leftIndex+1 <= lastInddex) { int rightIndex = leftIndex + 1; if (heap[rightIndex] > heap[leftIndex]) { largerIndex = rightIndex; } } if (orphan < heap[largerIndex]) { heap[rootIndex] = heap[largerIndex]; rootIndex = largerIndex; leftIndex = rootIndex * 2 + 1; } else { done = true; } } heap[rootIndex] = orphan; }
用堆解决这个问题其实思路并不难,前提是,需要对堆有一定的理解。
作者:Ribbon 出处: http://www.cnblogs.com/Ribbon/
本文版权归作者和博客园共有,欢迎转载。未经作者同意下,必须在文章页面明显标出原文链接及作者,否则保留追究法律责任的权利。
如果您认为这篇文章还不错或者有所收获,可以点击右下角的【推荐】按钮,因为你的支持是我继续写作,分享的最大动力!