编程之找寻最大的K个数

解法一是最基本的排序算法,本文略过。

解法四依赖最大堆这个数据结构,多用于海量数据处理,本文略过。

重点实现了解法二和解法三。

解法二的思想是利用快排的以O(n)的时间得到某个数组中任意元素序号p,有A[i] <= A[x], r<=i<=p, A[j] > A[p], p<j<=r, 然后再配合二分查找,可以得到O(n*lgK)的算法。该算法比解法三要容易理解,但是在实际做的过程中,发现最大的问题在于边界条件的处理,即应注意数组下标和元素个数是两个不同的概念,两者混淆的话很容易把自己绕进去,另外从完备性的角度考虑还应考虑异常处理,如果数组中所有元素为同一数值,那么该解法会导致死循环,该如何处理?

解法三则从数值的角度采用了二分搜索。是一种不同的思路,相比较解法二,我认为这种方法是实现难度最低的。效率同样也是O(n*lgK)


  1. // FindMaxK.cpp : Defines the entry point for the console application.   
  2. //   
  3.   
  4. #include "stdafx.h"   
  5. #include <stdlib.h>   
  6.   
  7. void swap(int A[], int i, int j)  
  8. {  
  9.     int t = *(A + i);  
  10.     *(A + i) = *(A + j);  
  11.     *(A + j) = t;   
  12. }  
  13.   
  14. int partition(int A[], int r, int q)  
  15. {  
  16.     if(r < q)  
  17.     {  
  18.         int t = r + rand() % (q - r) + 1;  
  19.         swap(A, t, r);  
  20.         int j = r;  
  21.         for(int i = r + 1; i <= q; i++)  
  22.         {  
  23.             if(A[i] <= A[r])  
  24.             {  
  25.                 j++;  
  26.                 swap(A, i, j);  
  27.             }  
  28.         }  
  29.         swap(A, r, j);  
  30.         return j - r;  
  31.   
  32.     }  
  33.     return -1;  
  34. }  
  35.   
  36. void FindMaxK1(int A[], int r, int q, int k)  
  37. {  
  38.     int p = partition(A, r, q);  
  39.     if( p > k )  
  40.     {  
  41.         FindMaxK1(A, r, p,k);  
  42.     }  
  43.     else if( p < k )  
  44.     {  
  45.         FindMaxK1(A, p + 1, q,k - p );  
  46.     }  
  47.   
  48. }  
  49.   
  50.   
  51. int count(int A[], int len, float v)  
  52. {  
  53.     int count = 0;  
  54.     for(int i = 0; i < len; i++)  
  55.     {  
  56.         if(A[i] >= v)  
  57.             count++;  
  58.     }  
  59.     return count;  
  60. }  
  61.   
  62.   
  63. int FindMax2(int A[], int len, int k)  
  64. {  
  65.     if(len <= 0)  
  66.         return -1;  
  67.     float min = A[0];  
  68.     float max = A[0];  
  69.     for(int i = 0; i < len; i++)  
  70.     {  
  71.         if(A[i] > max)  
  72.             max = A[i];  
  73.         if(A[i] < min)  
  74.             min = A[i];  
  75.     }  
  76.   
  77.     float delta = 0.5;  
  78.   
  79.     while ( max - min > delta )  
  80.     {  
  81.         float mid = min + (max - min) / 2;  
  82.         if(count(A, len, mid) > k)  
  83.         {  
  84.             min = mid;  
  85.         }  
  86.         else  
  87.         {  
  88.             max = mid;  
  89.         }  
  90.     }  
  91.   
  92.     for(int i = 0; i < len; i++)  
  93.     {  
  94.         if(A[i] >= min && A[i] <= max)  
  95.             return A[i];  
  96.     }  
  97.       
  98. }  
  99.   
  100.   
  101.   
  102. enum {len = 6};  
  103.   
  104. void Test()  
  105. {  
  106.     int A[] = {4,3,1,7,5,2};  
  107.     int k = 3;  
  108.     FindMaxK1(A, 0, len - 1, k);  
  109.     for(int i = 0; i < len; i++)  
  110.     {  
  111.         printf("%d ", A[i]);  
  112.     }  
  113.     int v = FindMax2(A, len, k);  
  114.     printf("%d ", v);  
  115. }  
  116.   
  117. int _tmain(int argc, _TCHAR* argv[])  
  118. {  
  119.     Test();  
  120.     return 0;  
  121. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值