2-1 众数问题
2016-09-19 20:49
253 查看
给定含有n个元素的多重集合S,每个元素在S中出项的次数称为该元素的重数。多重集S中重数最大的元素称为众数。
例如S={1,2,2,2,3,5}。多重集S的众数是2,其重数为3.
算法一:使用C++STL的map容器关键字作为元素,值为出现发的次数
算法二:
使用数组排序后,找出众数。时间复杂度O(NlogN);
.
算法三(分治与递归):
时间复杂度分析:
![](https://img-blog.csdn.net/20160926130750392?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
代码:
例如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 100 int a ; /* 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 ; 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; }