004-寻找多数元素-归纳法-《算法设计技巧与分析》M.H.A学习笔记

含有n个元素的序列,多数元素指出现次数多于n/2的元素。

 

不漂亮的算法:

朴素:依次将每个元素同其他元素比较,统计其出现次数,Θ(n2)

排序并寻找中间元素:排序这一块就是O(nlogn),中间元素可能是多数元素,还需要扫一遍序列确定,Θ(n)

 

漂亮的算法:

这是一个Θ(n)的算法,基于下面这个结论:

 

在原序列中去除两个不同的元素后,那么在原序列中的多数元素在新序列中还是多数元素。

 

仔细理解选择候选者元素的candidate()方法,这一结论的作用就在这里体现。

 基本思路:

寻找候选者(唯一的一个可能为多数元素的值,相当于中间元素)的过程:

(1)计数器count1,另c=A[1];

(2)A[2]开始向后扫描,

for j=2 to n

a[j]c相等,则count++;

a[j]c不等,则count

count==0,则对A[j+1...n]寻找多数元素候选者(这里的情况就是前面有几对不相等的数,于是就统统去掉,在剩余的数中寻找候选者,结论用在这里)。

If j=n then return c(返回可能的候选者c

end for

 

得到候选者元素后,我们只需要扫一遍序列,确认候选元素是否为多数元素就好了。

这两个过程都是Θ(n)的。

伪代码:

 

C++代码:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3.   
  4. int candidate(int p[],int m,int n){  
  5.     int j = m;  
  6.     int c = p[m];  
  7.     int count = 1;  
  8.     while( j < n&&count > 0){  
  9.            j ++;  
  10.            if(p[m] == c) count ++;  
  11.            else count --;  
  12.            }  
  13.     if(j == n)  return c;  
  14.     else return candidate(p,j + 1,n);  
  15. }  
  16.   
  17.   
  18. int main(){  
  19.     int i;  
  20.     int n;  
  21.     int c;  
  22.     int *p;    
  23.     while(scanf("%d",&n)!=EOF)  
  24.     {                                                
  25.        p = (int *)malloc(n*sizeof(int));  
  26.        for(i = 0;i < n;i ++){               
  27.            scanf("%d",&p[i]);                             
  28.            }  
  29.        c = candidate(p,0,n);//寻找多数元素   
  30.        int count = 0;  
  31.        for(i = 0;i < n;i ++){  
  32.              if(p[i] == c)  count ++;  
  33.              }  
  34.        if(count > n/2)  
  35.                 printf("%d\n",c);  
  36.     }  
  37.     system("pause");  
  38.     return 0;  
  39. }<span style="color: rgb(54, 46, 43); font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>  

推导出迭代版本:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3.    
  4. int candidate(int p[],int n){  
  5.     int j = 0;  
  6.     int c;  
  7.     int count;  
  8.     while(j != n){  
  9.             c = p[j];  
  10.             count = 1;  
  11.             while( j < n&&count > 0){  
  12.                   j ++;  
  13.                   if(p[j] == c) count ++;  
  14.                   else count --;  
  15.                   }  
  16.                   if(j == n)  return c;  
  17.                   else  j ++;  
  18.         }  
  19. }  
  20.    
  21. int main(){  
  22.     int i;  
  23.     int n;  
  24.     int c;  
  25.     int *p;    
  26.     while(scanf("%d",&n)!=EOF)  
  27.     {                                      
  28.       p = (int *)malloc(n*sizeof(int));  
  29.       for(i = 0;i < n;i ++){              
  30.           scanf("%d",&p[i]);                            
  31.           }    
  32.       c = candidate(p,n);//寻找多数元素  
  33.       int count = 0;  
  34.       for(i = 0;i < n;i ++){  
  35.             if(p[i] == c)  count ++;  
  36.             }  
  37.       if(count > n/2)  
  38.                 printf("%d\n",c);  
  39.       //free(p);  
  40.     }  
  41.     return 0;  
  42. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这波lucio来全学了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值