查找整型数组里出现频率最高的数字的最佳JAVA实现

来源:互联网 发布:乐乎网站 编辑:程序博客网 时间:2024/05/21 20:26
  1. package test;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Arrays;   
  5. import java.util.List;   
  6.   
  7. /**  
  8.  * 查找整型数组里出现频率最高的数字的最佳JAVA实现。  
  9.  *   
  10.  * @author 
  11.  */  
  12. public class HelloWindowExample {   
  13.   public static void main(String[] args) {   
  14.     test1();   
  15.     test2();   
  16.     testLaoZiZhu();   
  17.     testLaoZiZhuCounter();   
  18.     testLaoZiZhuCounter2();   
  19.   }   
  20.   
  21.   /**  
  22.    * 方法1<br>  
  23.    * 一个数组记录了每个数字出现的次数,长度和原始数组相同。<br>  
  24.    * 每个数组,向前查找相同的数字,如果找到则当前的次数等于上次的次数+1<br>  
  25.    * 如果没找到,则当前数字的次数为1.<br>  
  26.    * <br>  
  27.    * [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]<br>  
  28.    * [1, 2, 0, 0, 0, 0, 0, 0, 0, 0]<br>  
  29.    * [1, 2, 1, 0, 0, 0, 0, 0, 0, 0]<br>  
  30.    * [1, 2, 1, 3, 0, 0, 0, 0, 0, 0]<br>  
  31.    * [1, 2, 1, 3, 1, 0, 0, 0, 0, 0]<br>  
  32.    * [1, 2, 1, 3, 1, 4, 0, 0, 0, 0]<br>  
  33.    * [1, 2, 1, 3, 1, 4, 2, 0, 0, 0]<br>  
  34.    * [1, 2, 1, 3, 1, 4, 2, 3, 0, 0]<br>  
  35.    * [1, 2, 1, 3, 1, 4, 2, 3, 4, 0]<br>  
  36.    * [1, 2, 1, 3, 1, 4, 2, 3, 4, 1]<br>  
  37.    * 5 4<br>  
  38.    * 3 4<br>  
  39.    */  
  40.   public static void test1() {   
  41.     int[] ar = { 5585353331 };   
  42.     int[] fr = new int[ar.length];   
  43.     int top = 0;   
  44.     int i, j;   
  45.     for (i = 0; i < fr.length; i++) {   
  46.       // 从当前位置向前查找,和当前数字相同的位置   
  47.       j = i - 1;   
  48.       while (j >= 0) {   
  49.         if (ar[j] == ar[i]) {   
  50.           // 找到了,退出   
  51.           break;   
  52.         }   
  53.         // 否则继续向前找   
  54.         j--;   
  55.       }   
  56.       if (j < 0) {   
  57.         // 如果没有找到,则设置次数为1   
  58.         fr[i] = 1;   
  59.       } else {   
  60.         // 如果找到了,则次数为上一个的次数+1   
  61.         fr[i] = fr[j] + 1;   
  62.       }   
  63.       // 记录最大的次数   
  64.       if (fr[i] > top) {   
  65.         top = fr[i];   
  66.       }   
  67.       // System.out.println(Arrays.toString(fr));   
  68.     }   
  69.     for (i = 0; i < fr.length; i++) {   
  70.       if (fr[i] == top)   
  71.         System.out.println("" + ar[i] + " " + top);   
  72.     }   
  73.   }   
  74.   
  75.   /**  
  76.    * 使用列表,在找到重复数据后,删除列表的数据<br>  
  77.    * 这样下次循环时次数将减少。<br>  
  78.    * 不过其使用了字符串,效率不是很高,但思路很好。  
  79.    */  
  80.   public static void test2() {   
  81.     String[] array = { "5""5""8""5""3""5""3""3""3""1" };   
  82.     List list = Arrays.asList(array);   
  83.     list = new ArrayList(list);   
  84.     List outValue = new ArrayList();   
  85.     int count = 0;   
  86.     // 循环,直到列表里不再有数据   
  87.     while (list.size() - 1 > 0) {   
  88.       // 拿到最后一个数据   
  89.       String element = (String) list.get(list.size() - 1);   
  90.       // 计数   
  91.       int tempCount = 0;   
  92.       // 向前查找相同的   
  93.       for (int j = list.size() - 1; j >= 0; j--) {   
  94.         // 如果找到,则计数加1,然后从列表删除   
  95.         // 这也是为何要从末尾开始循环的理由   
  96.         if (element.equals(list.get(j))) {   
  97.           tempCount++;   
  98.           list.remove(j);   
  99.         }   
  100.       }   
  101.       // 如果这个计数最大,则更新输出的数据   
  102.       if (tempCount > count) {   
  103.         count = tempCount;   
  104.         outValue.clear();   
  105.         outValue.add(element);   
  106.       } else if (tempCount == count) {   
  107.         // 否则加入到最大数的列表里   
  108.         outValue.add(element);   
  109.       }   
  110.     }   
  111.     System.out.println("出现频率最高的是:" + outValue + "/n出现了:" + count + "次");   
  112.   }   
  113.   
  114.   /**  
  115.    * 我的精心设计<br>  
  116.    * 不使用列表,而是直接用整型数组进行操作,速度最快.<br>  
  117.    * 思路和前面列表的相同,但不是进行删除,而是将当前位置的数据设置为尾部的数据。<br>  
  118.    * 等同于数据交换,将不再用的数据移动到尾部就行了.<br>  
  119.    * 数组的速度比列表要快太多了。  
  120.    */  
  121.   public static void testLaoZiZhu() {   
  122.     int[] ar = { 5585353331 };   
  123.     List<Integer> outValue = new ArrayList<Integer>();   
  124.     int count = 0;   
  125.     // 这个是剩余可用的总数   
  126.     int has = ar.length;   
  127.     int element;   
  128.     int tempCount;   
  129.     System.out.println(Arrays.toString(ar));   
  130.     // 循环,直到列表里不再有数据   
  131.     while (has > 0) {   
  132.       // 拿到最后一个数据   
  133.       element = ar[has - 1];   
  134.       // 计数   
  135.       tempCount = 0;   
  136.       // 向前查找相同的   
  137.       for (int j = has - 1; j >= 0; j--) {   
  138.         // 如果找到,则计数加1,然后将数据和末尾交换   
  139.         // 这也是为何要从末尾开始循环的理由   
  140.         if (element == ar[j]) {   
  141.           tempCount++;   
  142.           // 将当前位置交换为末尾的数据   
  143.           // 注意末尾数据是动态变化的   
  144.           ar[j] = ar[has - 1];   
  145.           has--;   
  146.         }   
  147.       }   
  148.       System.out.println(Arrays.toString(ar));   
  149.       // 如果这个计数最大,则更新输出的数据   
  150.       if (tempCount > count) {   
  151.         count = tempCount;   
  152.         outValue.clear();   
  153.         outValue.add(element);   
  154.       } else if (tempCount == count) {   
  155.         // 否则加入到最大数的列表里   
  156.         outValue.add(element);   
  157.       }   
  158.     }   
  159.     System.out.println("出现频率最高的是:" + outValue + "/n出现了:" + count + "次");   
  160.   }   
  161.   
  162.   /**  
  163.    * 计数法,前提是数字都是正数。<br>  
  164.    */  
  165.   public static void testLaoZiZhuCounter() {   
  166.     int[] ar = { 5585353331 };   
  167.     // 找到最大的数   
  168.     int max = ar[0];   
  169.     for (int i = 1; i < ar.length; i++) {   
  170.       if (ar[i] > max) {   
  171.         max = ar[i];   
  172.       }   
  173.     }   
  174.     // 构建技术数组   
  175.     int[] vote = new int[max + 1];   
  176.     int countMax = 0;   
  177.     // 开始计数   
  178.     for (int i = 0; i < ar.length; i++) {   
  179.       vote[ar[i]]++;   
  180.       if (vote[ar[i]] > countMax) {   
  181.         countMax = vote[ar[i]];   
  182.       }   
  183.     }   
  184.     // 输出结果   
  185.     for (int i = 0; i < vote.length; i++) {   
  186.       if (vote[i] == countMax) {   
  187.         System.out.print(i + ",");   
  188.       }   
  189.     }   
  190.     System.out.println("出现次数为" + countMax);   
  191.   }   
  192.   
  193.   /**  
  194.    * 计数法,前提是数字都是正数。<br>  
  195.    * 支持负数的情况  
  196.    */  
  197.   public static void testLaoZiZhuCounter2() {   
  198.     int[] ar = { 5585, -35, -3, -3, -31 };   
  199.     // 找到最大的数   
  200.     int max = ar[0];   
  201.     int min = ar[0];   
  202.     for (int i = 1; i < ar.length; i++) {   
  203.       if (ar[i] > max) {   
  204.         max = ar[i];   
  205.       } else if (ar[i] < min) {   
  206.         min = ar[i];   
  207.       }   
  208.     }   
  209.     // 构建技术数组   
  210.     int[] vote = new int[max - min + 1];   
  211.     int countMax = 0;   
  212.     // 开始计数   
  213.     for (int i = 0; i < ar.length; i++) {   
  214.       // 调整   
  215.       vote[ar[i] - min]++;   
  216.       if (vote[ar[i] - min] > countMax) {   
  217.         countMax = vote[ar[i] - min];   
  218.       }   
  219.     }   
  220.     // 输出结果   
  221.     for (int i = 0; i < vote.length; i++) {   
  222.       if (vote[i] == countMax) {   
  223.         System.out.print((i + min) + ",");   
  224.       }   
  225.     }   
  226.     System.out.println("出现次数为" + countMax);   
  227.   }   
  228. }