算法設計與分析: 2-2 眾數問題


問題描述

給定含有n個元素的多重集合S,每個元素在S中出現的次數稱為該元素的重數。多重集S中重數最大的元素稱為眾數。例如,S={1,2,2,2,3,5}。多重集S的眾數是2,其重數為3。對於給定的n個自然數組成的多重集S,計算S的眾數及其重數 。

 

數組實現  

缺點:復雜度高

 1 package cn.htu.test;
 2 
 3 import java.util.Arrays;
 4 
 5 public class TestZhongShu01 {
 6 
 7     public static void main(String[] args) {
 8         int[] numbers = {1, 2, 2, 2, 3, 5};
 9         
10         int maxNum = Arrays.stream(numbers).max().getAsInt();
11         //.stream()可以把Arrays對象轉換為流,然后用stream的.max()找出流的最大元素.作為整數返回getAsInt()
12         //查幫助文檔的時候要注意Array和Arrays不同
13         
14         int[] count = new int[maxNum+1];//創建一個count數組,下標從0到maxNum
15         //如此一來,所有范圍的數都可以在count數組中以下標的形式找到
16 
17         for(int i=0; i<numbers.length; i++){
18             count[numbers[i]]++;
19             //將numbers數組的情況映射到count數組上去
20         }
21 
22         int tmpCount = 0;
23         int tmpValue = 0;
24         
25 
26         for(int i=0; i<=maxNum; i++){
27             if(count[i] > tmpCount){
28                 tmpCount = count[i];
29                 tmpValue = i;//始終記得count的下標和numbers的元素值對應
30             }
31         }
32 
33         System.out.println("The number: "+tmpValue+" appeared most times: "+tmpCount);
34     }
35 }

分治法實現

 

 1 package cn.htu.test;
 2 
 3 import java.util.Arrays;
 4 
 5 public class TestZhongShu01 {
 6     private static int[] numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 2, 2, 3, 4, 5};
 7 
 8     private static int leftest = 0;//數組最左邊的下標
 9     private static int rightest = numbers.length-1;//數組的最右邊的下標
10     private static int left, right;
11 
12     private static int count=0;
13     private static int number;
14 
15     public static void main(String[] args) {
16 
17         Arrays.sort(numbers);//先進行一次排序
18 
19         mode(leftest, rightest);//將leftrest和rightest,數組兩端下標傳入自定義函數mode
20 
21         System.out.println("The number: "+number+" appeared most times: "+count);
22     }
23 
24     private static void mode(int l, int r){
25 
26         int midIndex = getMidIndex(l, r);//自定義函數getMidIndex返回中位數下標
27         split(numbers, midIndex, l, r);//傳入數組,中間下標,最左下標和最右端下標,最后函數的作用是將left和right下標移動位置,到達中位數的左邊
28 
29         if(count < right-left+1){
30             count = right-left+1;//代表最大重數,剛開始代表中位數的重數
31             number = numbers[midIndex];//代表最大重數對應的眾數,剛開始填充的是中位數
32         }
33         //下面是分治法的內核
34         //如果左邊的數目或者右邊的數目多於最大重數就進行遞歸
35         if(left-l > count)
36             mode(l, left-1);
37         if(r-right > count)
38             mode(right+1, r);
39     }
40 
41     private static int getMidIndex(int l, int r){
42         return (l+r)/2;
43     }
44 
45     private static void split(int[] numbers, int midIndex, int l, int r)
46     {
47         //用left和right都指向中位數下標
48         left = midIndex;
49         right = midIndex;
50 
51         while (left-1 >=l && numbers[--left] == numbers[midIndex]);//left下標一直左移除非左移的那個數不是和中位數相等
52         while (right+1<=r && numbers[++right] == numbers[midIndex]);//right下標一直右移,除非右移的那個數和中位數不相等
53         
54         //循環之后的left和right下標之間的距離就是中位數的重數
55         
56         if(numbers[l] != numbers[midIndex])//把left下標移到中位數左邊的那一位,如果相同那就沒必要挪動了
57             left++;
58         if(numbers[r] != numbers[midIndex])
59             right--;
60     }
61 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM