眾數問題-遞迴和分治
阿新 • • 發佈:2019-01-30
問題描述
給定一個數組,找出其中出現次數最多的那個元素(即眾數)。
例如:
1 2 2 2 3 5
眾數是: 2
演算法思路:先排序 後用分治法計算求解
分治法求解程式碼如下:
#include <iostream> #include <stdlib.h> #include <time.h> using namespace std; /*----------快速排序*/ int Partition(int *a , int l , int r) { int i = l , j = r+1; int x = a[l]; while(true){ while(a[++i] < x && i < r); while(a[--j] > x); if(i >= j) break; swap(a[i] , a[j]); } a[l] = a[j]; a[j] = x; return j; } /*------------隨機選擇中位數排序*/ int RandomizedPartitiom(int *a , int l , int r) { srand(time(NULL)); int i = rand()%(r-l)+l; swap(a[i] , a[l]); return Partition(a , l , r); } /*----------------按中位數劃分成兩段*/ void split(int *a , int m , int l , int r , int *left , int *right) { int med = a[m]; *left = *right = m; /*--------------------將 == 中位數的元素剔除:及 right-left+1 == 眾數的個數*/ while(a[--(*left)] == med); while(a[++(*right)] == med); (*left)++; (*right)--; } /*---------------分治法求解*/ void mode(int *a , int l , int r , int *largest , int *count) { int m = RandomizedPartitiom(a , l , r);//----查詢中位數 int left , right; split(a , m , l , r , &left , &right);//---按中位數分成2段 if(*largest < right-left+1){//-----保留眾數個數最大值,及眾數下標 *largest = right-left+1; *count = m; } if(left-l > *largest) mode(a , l , left-1 , largest , count);//左邊個數大於眾數個數 if(r-right > *largest) mode(a , right+1 , r , largest , count);//右邊個數大於眾數個數 } /*----------main()*/ int main() { int n; cout<<"請輸入集合S的元素個數n:"<<endl; cin>>n; int a[n]; int largest = 0 , count = 0; cout<<"請輸入元素:"<<endl; for(int i = 0 ; i < n ; i++) cin>>a[i]; mode(&a[0] , 0 , n-1 , &largest , &count); cout<<"眾數是:"<<a[count]<<"\t重數是:"<<largest<<endl; return 0; } /* 請輸入集合S的元素個數n: 6 請輸入元素: 1 2 2 2 3 5 眾數是:2 重數是:3 Process returned 0 (0x0) execution time : 7.504 s Press any key to continue. */