众数问题-分治
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
众数问题-分治
题⽬:
找出给定递增序列的众数,并求出众数在序列中出现的次数(重数)
思路:
⼀开始看到题⽬写的时候,⽤的是O(n)级别的⼀遍扫描法,边扫描边统计,现在⽤分治法来写⼀下
对于⼀个数组,⾸先我假设中间元素是众数,并且⽤区间内扫描法来定位所有与中间数相等的数,区间标记为[p,r],个数记为midcnt
这样就通过p,r将区间分成了三段,接下来要做的应该是向[left,p-1]和[r+1,right]分别拓展,看这两个区间内是否会出现众数
在拓展的时候我们可以做⼀个优化,如果某个区间所有的元素个数⽐中与间元素(⽬前假设的众数)相等的数的个数还少,那么这个区间内不可能出现众数,可以不⽤再去找,如果找到的新的数⽐⽬前的重数⼤,则新的众数诞⽣。
上代码:
1 #include<iostream>
2using namespace std;
3int a[] = { 1,1,2,2,2,3,3,3,3,3,4,4,5,6,7,7,7 };
4int len = sizeof(a) / sizeof(a[0]);
5int num;
6int cnt=0;
7void pos(int left, int right,int mid, int &p, int &r) {
8int i;
9for (i = left; i <= right; i++) {
10if (a[i] == a[mid]) {
11break;
12 }
13 }
14 p = i;//mid的左边界
15for (i = p + 1; i <= right; i++) {
16if (a[i] != a[mid]) {
17break;
18 }
19 }
20 r = i - 1;//mid的右边界
21 }
22void getMaxCnt(int left, int right) {
23int mid = (left + right) / 2;
24int p;
25int r;
26 pos(left, right, mid, p, r);
27int midcnt = r - p + 1;
28if (midcnt > cnt) {
29 num = a[mid];
30 cnt = midcnt;
31 }
32if (p - left > cnt) {
33 getMaxCnt(left, p - 1);
34 }
35if (right - r - 1 > cnt) {
36 getMaxCnt(r + 1, right);
37 }
38 }
39int main() {
40 getMaxCnt(0, len - 1);
41 cout << num << endl;
42 cout << cnt << endl; 43
44return0;
45 }。