寻找数组中超过一半的元素,这是一道十分经典和普遍的面试题了,实现起来比较容易,只是需要写技巧,将问题扩展就可以衍生到求数组中几个超过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就是所求的元素。