编程之美-得到无序数组中最大K个数


原文看这里:

题目描述:
问:有很多个无序的数,我们姑且假定他们各不相等,怎么选出其中最大的若干个数呢?
答:可以这样写:int array[100] 。。。
问:好,如果有更多的数呢?
答:那可以改为 int array[1000] ...
问:如果我们有很多的数,比如一亿个,怎么办?
答:我们可以写 float array[100000000] 。。。
问:这样的程序能编译运行吗?
答:嗯... 我没写过那么多的0 .....


以下是各种实现的代码,我们就不用1亿个数字测试了,如果真的有那么多,保存为文件,用InputStream一边读取,一边处理好了:

注意:代码里面的大部分for循环,都可以改成从InputStream进行读取,int[]参数也是一样。这样就可以处理大数据量了。
  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.List;
  4. /**
  5.  * 得到无序数组的最大的K个数据。
  6.  * 
  7.  * @author 老紫竹 java2000.net
  8.  */
  9. public class ArrayFind {
  10.   public static void main(String[] args) {
  11.     int[] arrNum = { 15835872568495226163313656513334,
  12.         2423647444 };
  13.     List<Integer> arr = new ArrayList<Integer>(arrNum.length);
  14.     for (int num : arrNum) {
  15.       arr.add(num);
  16.     }
  17.     List<Integer> arrBak = new ArrayList<Integer>(arr);
  18.     int k = 5;
  19.     find1(arr, k);
  20.     //
  21.     //
  22.     arr.clear();
  23.     arr.addAll(arrBak);
  24.     List<Integer> rtn = find2(arr, k);
  25.     for (int num : rtn) {
  26.       System.out.print(num + ",");
  27.     }
  28.     System.out.println();
  29.     //
  30.     //
  31.     arr.clear();
  32.     arr.addAll(arrBak);
  33.     find3(arr, k);
  34.     //
  35.     //
  36.     arr.clear();
  37.     arr.addAll(arrBak);
  38.     List<Integer> rtn4 = find4(arr, k);
  39.     for (int num : rtn4) {
  40.       System.out.print(num + ",");
  41.     }
  42.     System.out.println();
  43.   }
  44.   /**
  45.    * 标准排序算法。
  46.    * 
  47.    * @param arr
  48.    * @param k
  49.    */
  50.   public static void find1(List<Integer> arr, int k) {
  51.     Collections.sort(arr);
  52.     for (int i = arr.size() - 1; i > arr.size() - k - 1; i--) {
  53.       System.out.print(arr.get(i) + ",");
  54.     }
  55.     System.out.println();
  56.   }
  57.   /**
  58.    * 大小组分组方法。
  59.    * 
  60.    * @param S
  61.    * @param k
  62.    * @return
  63.    */
  64.   public static List<Integer> find2(List<Integer> S, int k) {
  65.     if (k <= 0) {
  66.       return new ArrayList<Integer>();
  67.     }
  68.     if (S.size() <= k) {
  69.       return S;
  70.     }
  71.     List<Integer>[] rtn = Partition(S);
  72.     List<Integer> Sa = rtn[0];
  73.     List<Integer> Sb = rtn[1];
  74.     List<Integer> R = find2(Sa, k); // 找大的一组里面最大的k个
  75.     if (Sa.size() < k) {// 如果大的分组不足,则加上小的一组里面不够的数量
  76.       R.addAll(find2(Sb, k - Sa.size()));
  77.     }
  78.     return R;
  79.   }
  80.   private static List<Integer>[] Partition(List<Integer> S) {
  81.     ArrayList<Integer> Sa = new ArrayList<Integer>();
  82.     ArrayList<Integer> Sb = new ArrayList<Integer>();
  83.     int p = S.get(0);
  84.     int element;
  85.     for (int i = 1; i < S.size(); i++) {
  86.       element = S.get(i);
  87.       if (element > p) {
  88.         Sa.add(element);
  89.       } else {
  90.         Sb.add(element);
  91.       }
  92.     }
  93.     if (Sa.size() < Sb.size()) {
  94.       Sa.add(p);
  95.     } else {
  96.       Sb.add(p);
  97.     }
  98.     ArrayList<Integer>[] rtn = new ArrayList[2];
  99.     rtn[0] = Sa;
  100.     rtn[1] = Sb;
  101.     return rtn;
  102.   }
  103.   public static List<Integer> find3(List<Integer> S, int K) {
  104.     double Vmin = 0;
  105.     double Vmax = 1000;
  106.     double delta = 0.5;
  107.     double Vmid;
  108.     while (Vmax - Vmin > delta) {
  109.       Vmid = Vmin + (Vmax - Vmin) * 0.5;
  110.       int count = 0;
  111.       for (int n : S) {
  112.         if (n >= Vmid)
  113.           count++;
  114.         if (count >= K)
  115.           break;
  116.       }
  117.       if (count >= K) {
  118.         Vmin = Vmid;
  119.       } else {
  120.         Vmax = Vmid;
  121.       }
  122.     }
  123.     for (int s : S) {
  124.       if (s > Vmin) {
  125.         System.out.print(s + ",");
  126.       }
  127.     }
  128.     System.out.println();
  129.     return null;
  130.   }
  131.   /**
  132.    * 使用一个长度为K的小列表。
  133.    * 
  134.    * @param S
  135.    * @param K
  136.    * @return
  137.    */
  138.   public static List<Integer> find4(List<Integer> S, int K) {
  139.     List<Integer> rtn = new ArrayList<Integer>(K);
  140.     for (int i = 0; i < K; i++) {
  141.       rtn.add(S.get(i));
  142.     }
  143.     Collections.sort(rtn);
  144.     int min = rtn.get(0);
  145.     int current;
  146.     for (int i = K; i < S.size(); i++) {
  147.       current = S.get(i);
  148.       if (current > min) {
  149.         rtn.remove(0);
  150.         rtn.add(current);
  151.         Collections.sort(rtn);
  152.         min = rtn.get(0);
  153.       }
  154.     }
  155.     return rtn;
  156.   }
  157. }

运行结果
474,87,65,49,36,
474,87,65,49,36,
87,49,36,65,36,474,
36,49,65,87,474,
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值