算法設計:尋找多數元素


 

 

在上節的算法設計課堂上,我們學習了尋找多數元素的算法,這個算法相對於我們以前學習的算法比較不好理解,今天就讓我們來看看這個算法

1.思路解析

1.1多數元素定義

多數元素表示在一個數組中出現次數最多,並且出現次數 > 數組總長度的一半的元素。例如數組a = {1,7,5,5,5,5,5,4},數組總長度為8,5在其中出現了5次,大於8/2=4次,因此5是多數元素。

而在數組b = {1,2,5,5,5,9,7,6,4},數組總長度為9,5雖然同樣是出現次數最多的元素,但他的出現次數只有3次,因而不能算作多數元素。、

1.2遍歷計數法

遍歷計數法可謂是最簡單粗暴的方法,其思路是對數組中出現的每一個元素,都遍歷一遍求出其出現次數,再從中找出多數元素,這種算法的優點在於容易想到,但這種算法的計算量實在太大,因此不推薦

1.3排序取中項法

排序取中項法相對於前一個方法來說進步了一些,其使用的原理是:

  • 在一個排好序的數組中,其最中間的元素必定是多數元素(如果有的話)

但這種算法也有其劣勢,就是它要求數組進行排序,在數組長度較大的時候,其計算代價也是較大的

1.4剔除元素法(推薦方法)

因此我們使用推薦的算法,這個算法基於的原理是:

  • 在原序列中去除兩個不同的元素后,原序列中的多數元素在新序列中還是多數元素。

那么問題就簡單了,我們只需要將數組中不相同的元素兩兩剔除,那么剩下的數就自然是多數元素。

我們可以將數組的第一個元素設置為多數元素候選c,以及計數器count = 1,將數組后面的數與c比較,若相等count+1,不相等count-1,若count減到0,便表示該元素出現次數太少,將其和后面一個不相等的元素剔除,再次重置c和count,繼續此操作,直到比較到最后count都不為0,則c就為多數元素。

這種算法將復雜過程簡化成了兩數的比較,大大提升了計算效率。

2.算法偽碼

該算法的偽碼如下:

MAJORITY(n):

  1. c←candidate(1)
  2. count←0
  3. for j←1 to n
  4.     if a[j] = c then count←count+1
  5. end for
  6. if count > n/2(取下線) then return c
  7. else return none

candidate(m):

  1. j←m; c←a[m]; count←1
  2. while j<n and count>0
  3.     j←j+1
  4.     if a[j] = c then count←count+1
  5.     else count←count-1
  6. end while
  7. if j=n then return c
  8. else return candidate(j+1)

3.具體代碼

算法部分如下:

 1 //尋找多數元素算法練習
 2 public class Marjority {
 3     private int a[] = new int[50];    //定義存放數據的數組
 4     public int length;        //定義數組長度
 5     public Marjority(int length,int a[])
 6     {
 7         for(int i=1;i<=length;i++)
 8             this.a[i] = a[i-1];    //轉存數組
 9             /*需要注意的是,我們的算法中數組下標從1開始
10              * 但java存儲時的數組下標從0開始,所以轉存時下標需-1*/
11         this.length = length;
12     }
13     //尋找多數元素,若存在則輸出,不存在返回-99999
14     public int Mar()
15     {
16         int c = candidate(1);
17         //進行多數元素查詢
18         int count = 0;
19         for(int j=1;j<=length;j++)
20             if(a[j] == c)
21                 count++;    //計算該元素在數組中出現的次數
22         if(count > length/2)    //判斷出現次數是否大於長度的一半
23             return c;    //大於則有多數元素,返回其值
24         else return -9999;    //不大於則沒有多數元素,返回-9999
25     }
26     public int candidate(int n)
27     {
28         int j = n, c = a[n], count = 1;
29         //聲明數組索引,當前元素值,計數器
30         while(j<length && count>0)
31         {
32             j++;    //指針向后移動一位
33             if(a[j] == c)    //若下一位與當前元素相同,計數器增加
34                 count++;
35             else count--;    //否則計數器減少
36             /*這里不太好理解的是計數器的作用,
37              * 實際上計數器是一個篩選作用,
38              * 當當前元素重復出現的次數太少時,
39              * 將這個元素剔除出候選*/
40         }
41         if(j == length)
42             return c;    /*當指針指向最后一個元素時,
43                            表示當前元素出現次數足夠多,
44                            返回其值*/
45         else return candidate(j+1);    //否則繼續向后遍歷
46     }
47 }

 測試部分如下:

public class TestMarjority {
    public static void main(String args[])
    {
        int a[] = {1, 2, 5, 5, 5, 5, 5, 1, 3};    //含有多數元素的數組
        int b[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};    //不含有多數元素的數組
        Marjority m1 = new Marjority(a.length, a);
        Marjority m2 = new Marjority(b.length, b);
        System.out.println(m1.Mar());
        System.out.println(m2.Mar());
    }
}

 輸出結果如下:

 


免責聲明!

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



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