查找最小的k 个元素之C#算法实现
2014-03-29 13:57
351 查看
紧接着上一篇微软编程面试100题,这次想解决的是查找最小的K个元素,题目是:输入n 个整数,输出其中最小的k 个。例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。
看到题目的时候我第一反应,这题很简单,使用任何方式的排序将数列按顺序存储,之后遍历需要的k个元素即可,于是自己动手很容易就完成了,但是后来在网络上发现很多人对这题的解决方式是用小根堆(MinHeap)或者大根堆(MaxHeap),这才意识到,其实出题人是醉翁之意不在酒,在乎复杂度的考虑也。
先写用排序的方式完成题目的方式吧,不仅简单,不需要费太多脑子,重要的是,正好趁这时候复习下排序,这里用快速排序完成:
然后定义一个MinKMethod的方法来获取所需元素:
这么做的话,最快需要O(NlogN)的时间进行排序,然后在O(1)的时间内将k个数取出。
接下来看看如何用堆完成这个题:
用堆解决这个问题其实思路并不难,前提是,需要对堆有一定的理解。
看到题目的时候我第一反应,这题很简单,使用任何方式的排序将数列按顺序存储,之后遍历需要的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; }
用堆解决这个问题其实思路并不难,前提是,需要对堆有一定的理解。
相关文章推荐
- 设计一个最优算法来查找一n个元素数组中的最大值和最小值。已知一种需要比较2n次的方法,请给一个更优的算法。
- 微软等数据结构+算法面试100题(46)-- 查找最小的k 个元素
- 数据结构(C#)--图结构的实现输出以及图结构的深度和广度优先搜索和Dijkstra 算法的最小路径以及最小生成树的实现
- 用堆排序实现查找最小的K个元素 java
- 每天一道算法题4 查找最小的k个元素
- 算法数据结构C++实现7 - 同时查找最大值和最小值优化算法
- 查找最小的k个元素-堆的实现方法(下)
- 算法题12 查找最小的k个元素
- 算法代码实现之选出第k小元素、中位数、最小的k个元素(线性复杂度),Java实现
- C++ 算法 查找旋转数组中的最小值 允许重复元素
- 数据结构(C#)--Dijkstra 算法的最小路径的实现
- 算法之查找第k小的数和查找最小的k个元素
- 程序员面试题精选100题(05)-查找最小的k个元素[算法]
- 【算法总结-top K】堆--查找最小(大)的k个元素
- 算法讨论(四)--查找最小的k个元素
- 每天一算法(查找最小的k个元素(数组))
- 设计一个最优算法来查找n个元素数组中的最大值和最小值
- 每天一道算法题4 查找最小的k个元素
- 程序员面试题精选100题(05)-查找最小的k个元素[算法]
- 查找最小的k个元素[算法]