演算法設計--眾數和重數問題(分治法)

聰聰不匆匆發表於2016-10-19

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

問題分析:
1、 分治法
分治法解題過程主要分為分、治、合三個步驟“,應用該方法的基本過程如下:
(1) 將原問題分解為若干個規模較小的子問題
(2) 對這些子問題分別求解
(3) 對各個子問題的解進行合併

2、 眾數:一組資料中出現次數最多的數值,叫眾數。有時一組資料中有多個眾數。
重數:重數是指該眾數出現的次數。

3、 根據以下例項理解分治法求解眾數及其重數
給定含有n個元素的多重集合S,每個元素在S中出現的次數稱為該元素的重數。多重集S中重數最大的元素稱為眾數。
例如,S = {1,2,2,2,3,5}。
多重集S的眾數是2,其重數是3.

演算法實現:

// Test_01.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"

void split(int s[],int n,int &l,int &r){
    int mid = n/2;
    for(l = 0; l<n; ++l){
        if(s[l] == s[mid])
            break;
    }
    for(r = l+1;r<n;++r){
        if(s[r] != s[mid])
            break;
    }
}

//num表示眾數  maxCnt表示重數
void getMaxCnt(int &mid,int &maxCnt, int s[],int n){
    int l ,r;
    split(s,n,l,r);   //將陣列進行切割成兩端
    int num = n/2;
    int cnt = r - 1;

    if(cnt > maxCnt){
        maxCnt = cnt;
        mid = s[num];
    }

    //l表示左邊的個數,左邊的個數必須大於中位數的個數,才有進行搜尋的意義
    if(l+1 > maxCnt){
        getMaxCnt(mid, maxCnt, s, l+1);
    }

    //同理,右邊的個數將要大於中位數的個數才有繼續搜尋的意義,同時右邊陣列的起始位置進行改變
    if(n-r > maxCnt){
        getMaxCnt(mid, maxCnt, s+r, n-r);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int s[] = {1,2,2,2,3,5};
    int n = sizeof(s)/sizeof(s[0]);

    int maxCnt = 0;
    int num = 0;
    getMaxCnt(num ,maxCnt, s, n);
    printf("%d %d\n",num,maxCnt);
    return 0;
}

執行結果
由於初始陣列為int s[] = {1,2,2,2,3,5};所以執行結果中眾數為 2 重數為 3

2 3
請按任意鍵繼續. . .

相關文章