找出數組中出現次數最多的那個數——主元素問題


 

  方法一:以空間換時間,可以定義一個計數數組int count[101],用來對數組中數字出現的次數進行計數(只能針對數組中數字的范圍1~100),count數組中最大的元素對應的下標,即為出現次數最多的那個數。Java代碼如下:

public class SearchMuch {

    public static void candidate (int[] array)    // 找出數組中出現次數最多的那個數
    {
        int[] count = new int[101];                // 計數數組,每個元素的默認值為0
        for(int i = 0; i < array.length; i++)
        {
            count[array[i]]++;                    // 對應的計數值加1
        }
        int maxCount = count[0];
        int maxNumber = 0;
        for(int i = 1; i < 100; i++)            // 找出最多出現的次數
        {
            if(count[i] > maxCount)
                maxCount = count[i];
        }
        for(int i = 0; i < 100; i++)            // 找出出現最多次的那個數字
        {
            if(count[i] == maxCount)
                maxNumber = i;
        }
        System.out.println("出現次數最多的數字為:" + maxNumber);
        System.out.println("該數字一共出現" + maxCount + "次");
    }
}

 

  上例是一種典型的空間換時間算法(所需數組空間的大小完全取決於數組中數字的大小)。一般情況下,除非內存空間足夠大且數組中的數不是很大,否則一般不采用這種方法。

 

  方法二:使用HashMap,每個Entry的key存放數組中的數字,value存放該數字出現的次數,首先遍歷數組元素構造HashMap,然后遍歷每個Entry,找出最大value對應的key,即是出現次數最多的那個數。此算法的時間復雜度為O(n)。Java代碼如下:

public class SearchMuch {

    public static void candidate (int[] array)    // 找出數組中出現次數最多的那個數
    {
        // map的key存放數組中的數字,value存放該數字出現的次數
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        for(int i = 0; i < array.length; i++)
        {
            if(map.containsKey(array[i]))        
            {
                int formerValue = map.get(array[i]);
                map.put(array[i], formerValue + 1);    // 該數字出現的次數加1
            }
            else
            {
                map.put(array[i], 1);    // 該數字第一次出現
            }
        }
        Collection<Integer> count = map.values();
        // 找出map的value中最大值,也就是數組中出現最多的數字所出現的次數
        int maxCount = Collections.max(count);
        int maxNumber = 0;
        for(Map.Entry<Integer, Integer> entry : map.entrySet())
        {
            //得到value為maxCount的key,也就是數組中出現次數最多的數字
            if(entry.getValue() == maxCount)
            {
                maxNumber = entry.getKey();
            }
        }
        System.out.println("出現次數最多的數字為:" + maxNumber);
        System.out.println("該數字一共出現" + maxCount + "次");
    }
}

 

 

  方法三(針對出現次數超過一半的情況):可以用數對對消的思路假設數組如下{1, ?, 1, 1, 1, ?, 1, ?, ?},數組中?代表其他任意不為1的數字,顯然,出現次數最多的數為1,且超過了一半,我們可以把1與?匹配(當然,我們事先並不知道1就是出現次數最多的那個數,這里只是講可行的思路),一次匹配出一個<1,?>,最后剩余沒得到匹配的數還是1,就是超過一半的次數,代碼有時間再寫。

 

 

  方法四(針對出現次數超過一半的情況):利用快速排序的分割算法(partition)。任意選取一個基准pivot,調用partition()把數組分成兩個部分,小於pivot的部分和大於pivot的部分,而pivot就位於它們之間,把返回的pivot的索引與數組的中位索引middle進行比較,只要二者不相等就更新邊界:

while(pivot_index != middle)
{ 
    if (pivot_index < middle)
        left = pivot_index + 1;
    else 
        right = pivot_index - 1;
    pivot_index = partition(A, left, right);
}

  

  最后A[middle]必定就是數組A中出現次數超過一半的那個數

 

  方法五(針對出現次數超過一半的情況):蒙特卡羅算法

  


免責聲明!

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



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