寻找数组中超过一半的元素,这是一道十分经典和普遍的面试题了,实现起来比较容易,只是需要写技巧,将问题扩展就可以衍生到求数组中几个超过N分一的元素,例如找出数组中3个出现次数超过1/4的元素。
/*************************************************************************
> File Name: morethanharf.c
> Author: desionwang
> Mail: wdxin1322@qq.com
> Created Time: Tue 29 Oct 2013 05:43:14 PM CST
************************************************************************/
#include<stdio.h>
int find(int arr[], int len){
if(arr == NULL || len <= 0){
return -1;
}
int curr = arr[0];
int count = 1;
int i;
for(i = 1; i < len; i++){
if(curr == arr[i]){
count++;
}else{
count--;
if(count < 0){
curr = arr[i];
count = 1;
}
}
}
//check the array is valid or not
count = 0;
for(i = 0; i < len ; i++){
if(arr[i] == curr){
count++;
}
}
if(curr * 2 < len){
return -1;
}else{
return curr;
}
}
这种方法是每次消除两个不同的查询,当两个相邻的查询不同时,相应的计数减一,当相同是加一,当计数减为0时,该元素从被选中去除变为不确定。
以上是寻找超过二分之一的元素,当寻找两个超过三分之一的元素,或是N-1个超过N分之一的元素时,也同样可以采用这种思想,只要我们每次去掉N个不同的查询就可以,那样剩下的元素就是我们要找的元素。
问题可以这样求解,申请一个大小为N的map,开始遍历数组,如果:
1、遇到一个不在map中的元素,则插入map中,并将value置1
2、遇到一个在map中的元素,则将map中该元素的对应值加1,
当map中的元素个数等于N时,最map中的每个key都减一,key为零的元素直接删除,这样遍历知道数组遍历完,那么map中剩下的key就是所求的元素。