查找最小的K个元素

题目:输入n个整数,输出其中最小的k个。
例如输入123456788个数字,则最小的4个数字为1234
分析:这道题最简单的思路莫过于把输入的n个整数排序,这样排在最前面的k个数就是最小的k个数。只是这种思路的时间复杂度为O(nlogn)。我们试着寻找更快的解决思路。
我们可以开辟一个长度为k的数组。每次从输入的n个整数中读入一个数。如果数组中已经插入的元素少于k个,则将读入的整数直接放到数组中。否则长度为k的数组已经满了,不能再往数组里插入元素,只能替换了。如果读入的这个整数比数组中已有k个整数的最大值要小,则用读入的这个整数替换这个最大值;如果读入的整数比数组中已有k个整数的最大值还要大,则读入的这个整数不可能是最小的k个整数之一,抛弃这个整数。这种思路相当于只要排序k个整数,因此时间复杂可以降到O(n+nlogk)通常情况下k要远小于n,所以这种办法要优于前面的思路。

  1. 参考代码: 
  2. #include <set> 
  3. #include <vector> 
  4. #include <iostream> 
  5. using namespace std; 
  6. typedef multiset<int, greater<int> >   IntHeap; 
  7. /// 
  8. // find k least numbers in a vector 
  9. /// 
  10. void FindKLeastNumbers 
  11.       const vector<int>& data,               // a vector of data 
  12.        IntHeap& leastNumbers,                 // k least numbers, output 
  13.       unsigned int k                               
  14.        leastNumbers.clear(); 
  15.  
  16.       if(k == 0 || data.size() < k) 
  17.             return
  18.        vector<int>::const_iterator iter = data.begin(); 
  19.       for(; iter != data.end(); ++ iter) 
  20.        { 
  21.             // if less than k numbers was inserted into leastNumbers 
  22.             if((leastNumbers.size()) < k) 
  23.                    leastNumbers.insert(*iter); 
  24.  
  25.             // leastNumbers contains k numbers and it's full now 
  26.             else 
  27.              { 
  28.                   // first number in leastNumbers is the greatest one 
  29. IntHeap::iterator iterFirst = leastNumbers.begin();
  30.                   // if is less than the previous greatest number 
  31.                   if(*iter < *(leastNumbers.begin())) 
  32.                    { 
  33.                         // replace the previous greatest number 
  34.                          leastNumbers.erase(iterFirst); 
  35.                          leastNumbers.insert(*iter); 
  36.                    } 
  37.              } 
  38.        } 

题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。

1 在数据量不大的情况下,排序

2 维护一个最小k 的数组 ,复杂度 为 o(k * N)

3 为一个最小K个数的最大堆 o(log2 k * N)

题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。

1 在数据量不大的情况下,排序

2 维护一个最小k 的数组 ,复杂度 为 o(k * N)

3 为一个最小K个数的最大堆 o(log2 k * N)

  1. /*
  2. 查找最小的k 个元素
  3. 题目:输入n 个整数,输出其中最小的k 个。
  4. 例如输入1,2,3,4,5,6,7和8这8个数字,
  5. 则最小的4个数字为1,2,3和4。
  6. */ 
  7.  
  8. /*
  9. 思路 : 来一个数据处理一个 ,当来的数据量小于K 时 ,全部处理成最大堆,
  10.         然后之后来的,必须要小于最大堆的的最大值,才可以入堆,此时 只需更新 根节点,再调整堆。
  11. */ 
  12. # include<stdio.h> 
  13. # include<stdlib.h> 
  14. const int K = 5 ;//这里可以修改  
  15. const int MAXN = 1000; 
  16.  
  17. int max_heap[K+1] ;//维护一个 最大堆  
  18. int end ,maxPos; 
  19.  
  20.  
  21. void swap(int &a ,int &b) 
  22.     int t = a;a = b ; b = t; 
  23.  
  24.  
  25. int FindMax() 
  26.     int maxPos = 1; 
  27.     for(int i = 2 ;i <= K ; i ++) 
  28.         if(max_heap[i] >max_heap[maxPos] ) 
  29.             maxPos = i; 
  30.     return maxPos; 
  31. /*将数据插入到 数组中  插入排序的思想*/ 
  32. void insertMinHeap(int mdata) 
  33.     int i,child = 0; 
  34.     if(end == K +1 ) // 如果堆满   
  35.     {     
  36.     /*    int mmaxPos = FindMax();*/ 
  37.         if(mdata >= max_heap[1] ) // 如果大于等于该堆的最大值 不做任何改变 
  38.             return
  39.  
  40.         max_heap[1] = mdata; 
  41.         for(i = 1 ; i*2  <=  K ;i = child) 
  42.         { 
  43.             child = 2*i  ; 
  44.             if((i*2 +1 <= K && max_heap[i*2] < max_heap[i*2+1]) )//返回最大孩子的下表 
  45.                 child ++; 
  46.             if(max_heap[i] < max_heap[child]) 
  47.                 swap(max_heap[i] ,max_heap[child]); 
  48.             else  
  49.             { 
  50.                 break
  51.             } 
  52.         }         
  53.         return
  54.     } 
  55.  
  56.     max_heap[end ++] = mdata; 
  57.     for(i = end -1  ; i > 1 ; i /=2) 
  58.     { 
  59.         if(max_heap[i] > max_heap[i/2]) 
  60.             swap(max_heap[i] ,max_heap[i/2]); 
  61.         else  
  62.         { 
  63.             break
  64.         } 
  65.     } 
  66.      
  67. int main() 
  68.     int n,data; 
  69.     freopen("in.txt","r",stdin);//如果想从文件输入 将这句注释掉 1234 1 2 3 4 5 6 7 8 9 10 11   
  70.     end = 1; 
  71.     while(scanf("%d",&data)!=EOF) // 如果是手工输入 结束输入 按 ctrl + z 
  72.     { 
  73.         insertMinHeap(data); 
  74.  
  75.     } 
  76.      
  77.     for(int i = 1 ; i <= K ; i ++) //  
  78.         printf("%d ",max_heap[i]); 
  79.     printf("\n"); 
  80.  
  81.     return 0; 
您好,关于Python实现查找最小的k个数,我可以提供以下两种常见的方法: 方法一:使用堆 将数组前k个元素建立小根堆,然后遍历剩余元素,若比堆顶元素小,则将其加入堆中,同时将堆顶元素删除,最终堆中的k个元素即为所求。具体代码如下: import heapq def find_k_min(nums, k): if not nums or k <= 0 or k > len(nums): return None res = [] for i in range(k): heapq.heappush(res, nums[i]) for i in range(k, len(nums)): if nums[i] < res[0]: heapq.heappop(res) heapq.heappush(res, nums[i]) return res 方法二:使用快排的思想 使用快排的思想,每次选择一个基准元素,将小于基准元素的放在左边,大于等于基准元素的放在右边,然后判断基准元素的位置,若该位置等于k-1,则基准元素以及左边的元素就是所求;若该位置小于k-1,则在右半边继续查找;若该位置大于k-1,则在左半边继续查找。具体代码如下: def find_k_min(nums, k): if not nums or k <= 0 or k > len(nums): return None left, right = 0, len(nums)-1 while True: index = partition(nums, left, right) if index == k-1: return nums[:k] elif index < k-1: left = index + 1 else: right = index - 1 def partition(nums, left, right): pivot = nums[left] while left < right: while left < right and nums[right] >= pivot: right -= 1 nums[left] = nums[right] while left < right and nums[left] < pivot: left += 1 nums[right] = nums[left] nums[left] = pivot return left 希望能对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值