2-1 众数问题

来源:互联网 发布:淘宝网水晶家纺被子 编辑:程序博客网 时间:2024/06/03 15:54

给定含有n个元素的多重集合S,每个元素在S中出项的次数称为该元素的重数。多重集S中重数最大的元素称为众数。

例如S={1,2,2,2,3,5}。多重集S的众数是2,其重数为3.


算法一:使用C++STL的map容器关键字作为元素,值为出现发的次数


tip:简单遍历一遍时间复杂度为O(nlgn)map插入时间nlgn
#include <iostream>  #include <stdlib.h>  #include <fstream>  #include <map>    using namespace std;    int main()  {      ifstream input("input.txt",ios::in);      ofstream output("output.txt",ios::out);        if (!input)      {          cerr<<"input file could not be opened"<<endl;          exit(1);      }        map<int,int> number_count;     int n; input>>n;  int data; while(n--) { input>>data;number_count[data]++;} int _max=-1;      auto flag=number_count.begin(),it=number_count.begin();            for(;it!=number_count.end();it++)      {             if(it->second>_max)          {              flag=it;              _max=it->second;          }       }             output<<flag->first<<endl<<flag->second<<endl;         auto rep=++flag;          for(;rep!=number_count.end();rep++)     {     if(rep->second==flag->second)     {     output<<rep->first<<endl<<rep->second<<endl;   } }          return 0;  }  


算法二:

使用数组排序后,找出众数。时间复杂度O(NlogN);

//使用数组记录下所有的数值,经过排序后,两层for循环解出 //时间复杂度O(NlogN) #include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define N 100int a[N];/* int partition(int s,int e){int i=s;int j=e+1;int x=a[s];while(1){while(a[++i]<x&&x<e);while(a[--j]>x);if(i>=j)break;swap(a[i],a[j]);}swap(a[s],a[j]);return j;}void Qsort(int s,int e){if(s<e){int q=partition(s,e);}}*/ int main(){FILE *fp1=NULL,*fp2=NULL; if(!(fp1=fopen("input.txt","r"))){printf("input.txt open error!\n");return 0;}if(!(fp2=fopen("output.txt","w"))){printf("output.txt open error!\n");return 0;}int n;while(!feof(fp1)){fscanf(fp1,"%d",&n);for(int i=0;i<n;i++)fscanf(fp1,"%d",&a[i]);fgetc(fp1);//Qsort(0,n-1);sort(a,a+n); int _max=1,cnt=1;for(int i=1;i<n;i++){if(a[i]==a[i-1])//从第二个数字开始遍历,如果这个数和前面的数相同,则计数+1,否则计数记为1 cnt++;else{_max=max(_max,cnt);   cnt=1;//更新cnt的值 }}_max=max(_max,cnt);////该for循环是将众数输出,众数可能不只有一个 cnt=1;for(int i=1;i<n;i++){if(a[i]==a[i-1])cnt++;else{if(cnt==_max)fprintf(fp2,"%d\n%d\n",a[i-1],_max);cnt=1;}}if(cnt==_max)fprintf(fp2,"%d\n%d\n",a[n-1],_max);}fclose(fp1);fclose(fp2);printf("bingo!\n");return 0;}

.

算法三(分治与递归):
– 先根据某数X,将小于X的放于其左,大于X的放于其右– 统计X出现的次数T– 如果X左边数的个数>T,向左递归– 如果X右边数的个数>T,向右递归

时间复杂度分析:


代码:
#include <iostream>  #include <stdlib.h>  #include <fstream>  const int MAX=100;  using namespace std;       int Random(int p, int r){//随机化          //return rand()*(r-p)/32767+p;      return rand()%(r-p)+p;  }    void Swap(int* c, int* d){          int temp;           temp= *c;          *c = *d;          *d = temp;  }     //小于x放置左边,大于x的放置右边 int Partition(int* y, int p, int r){          int i = p, j = r+1;          int x = y[p];          while(true){                  while(y[++i]<x&&i<r);                  while(y[--j]>x);                  if(i>=j) break;                  Swap(&y[i],&y[j]);          }          y[p] = y[j];          y[j] = x;          return j;  }    int RandomizedPartition(int* y, int p, int r){          int i = Random(p,r);          Swap(&y[i],&y[p]);          return Partition(y,p,r);  }  void FindModeIndex(int* y,int i,int* left_index,int* right_index)  {          int mode=y[i];          int left=i;          int right=i;          while(y[--left]==mode);          while(y[++right]==mode);          left++;          right--;//最后一次等于mid的下标,因为已经将小于等于x的放在左侧//大于等于的放在右侧,所以right-left+1就是x的出现次数;                  *left_index=left;          *right_index=right;  }    void FindMode(int* y, int p, int r, int& mode, int& count){          int i = RandomizedPartition(y,p,r);          int left_index;          int right_index;                  int count_mid,count_left,count_right;          FindModeIndex(y,i,&left_index,&right_index);          count_mid=right_index-left_index+1;                  count_left=left_index-p;                  count_right=r-right_index;          if(count_mid>=count)          {              mode=y[i];              count=count_mid;          }                  //如果左边数的和大于等于统计的x的重数,左边递归求解;         if(count_left>=count_mid) FindMode(y,p,left_index-1,mode,count);          //如果右边数的和大于等于统计的x的重数,左边递归求解;if(count_right>=count_mid)  FindMode(y,right_index+1,r,mode,count);          return;  }  int main()  {      ifstream input("input.txt",ios::in);      ofstream output("output.txt",ios::out);        if (!input)      {          cerr<<"input file could not be opened"<<endl;          exit(1);      }        int n;      int mode;      int count;  input>>n;int a[n]; for(int i=0;i<n;i++)  input>>a[i];mode=MAX;      count=0;          FindMode(a,0,n-1,mode,count);      output<<mode<<endl<<count<<endl;         return 0;  }  




0 0
原创粉丝点击