算法入门:最少比较次数求最大/最小/第二大元素

来源:互联网 发布:linux 翻到最后一页 编辑:程序博客网 时间:2024/06/05 06:47

本文将解决三个问题:
input:A[1……n] 包含n个数字

output:
- A的最大值max
- A的最大值max和最小值min
- A的最大值max和第二大值

要求:比较的次数尽可能少


1.最大元素

如果使用排序的话,常见排序中比较快的有快速排序O(nlogn)。但是显然做一个线性遍历更加快。linear scan的时间复杂度为O(n) 。

max = A[1];for i=2 to n    if max < A[i]    max = A[i];return max


2.最大元素和最小元素

值得注意的是这里要求的是比较次数尽可能少,如果做两次linear scan的话是需要2n次比较的,如果使用下面这种方法的话可以将比较次数降低至3/2n。

min = A[1];max = A[2];for i = 1 to n     if A[i] < A[i+1]         if max < A[i+1]             max = A[i+1];         if min > A[i]             min = A[i];

对于每一对A[i]和A[i+1],要比较3次,总共有n/2对,所以比较次数是3/2n。

3.求最大元素和第二大元素

如果使用线性扫描的话还是要比较2n次,第一次找最大值,再在剩下的元素中找最大值作为整体的第二大值。这里有一种方法是:在2中假设最大元素为max,将所有与max进行过比较的数字拿出来找最大值,也就是整体的第二大值。


建立一个vector B来存储被击败的数字。它是一个链表,每个元素是一个数组,用来存储当前索引位置的元素击败过的数字,注意是把loser放到B中winner对应的坐标的位置。比如4,2,45,9四个数字,第一次比较2是loser所以把2放进B[1]的位置,1是winner 4的坐标。


这个图会比较清楚:
这里写图片描述

max(A,i,j){    if i = j        return i;    else        mid = ⌊(i+j)/2; // 向下取整        a = max(A,i,mid);// 递归        b = max(A,mid+1,j);    if A[a]>A[b]        insert A[b] into B[a];        return a;    if A[a]<A[b]        insert A[a] into B[b];        return b;}

最后在主函数中:

main(){    i = max(A,1,n);    traverse B[i] to find the secondMax;    return A[i],secondMax}
阅读全文
0 0
原创粉丝点击