[面试题] 已知比例,找出数组中出现较多的元素
2011-07-05 16:44
267 查看
问题摘自《编程之美》。问题1:一个无序数组中某一个元素A的出现次数大于总数的1/2,如何找到它?问题2:一个无序数组中,如果有三个元素A、B、C的出现次数都大于总数的1/4,如何找到它们? 答案1:a> 对数组排序,O(nlogn),然后遍历一下排好序的数组,O(n),找到最长的相同序列。(这是通用解法,然而由于A的出现大于1/2,《编程之美》中说直接取数组中位数即可)。无论如何,总体是O(nlogn)。b> 将数组元素顺序插入一个hash表,key不存在,则val=1;当key存在,val+=1;O(n)全部插入后,统计一下hash表中val最大的即可。缺点是需要使用hash表,空间复杂度高,在hash表中遍历原数组元素,可以保证是O(n)的。c> 我们发现,如果每次从数组中拿出两个不同的元素,那么可能有两种情况(1,这两个元素不包含A;2,其中一个元素是A),无论哪种情况,都可以保证数组剩下的元素中,A的出现次数还是大于1/2,所以重复的拿,最后剩下的必然是A。代码如下:
答案2:与答案1的第三种方法类似,每次从数组中拿出4个互不相同的元素,这样可以保证A、B、C在这4个互不相同的元素中出现至多1次,使得剩下的元素中,依然可以保证大于1/4的比例。从而最后剩下的三种元素就是结果。代码如下:
总结:可以发现,遇到这类问题,每次提取出一些元素,尽量保证提取出元素后,剩下的还能维持原来的比例,这样就将问题规模缩小了,另外这种方法是O(n)时间复杂度的,可以说基本上是最优的解法了。好了,如果有人问你,一个数在无序数组中出现次数大于等于总数的2/5,找出这个数,你会做了吗?
int FindMajority( int* arr, int count ) { int ret = arr[0]; int rep = 1; for( int i = 1; i < count; ++i ) { if( ret == arr[i] ) ++rep; else if( --rep == 0 ) ret = arr[i+1]; // 这里放心的使用i+1不担心越界,是因为前提条件是元素出现次数大于count/2 } return ret; }
答案2:与答案1的第三种方法类似,每次从数组中拿出4个互不相同的元素,这样可以保证A、B、C在这4个互不相同的元素中出现至多1次,使得剩下的元素中,依然可以保证大于1/4的比例。从而最后剩下的三种元素就是结果。代码如下:
// 由于有3个返回值,所以将它们放到参数列表里,而不是函数的返回值 int FindMajority3( int* arr, int count, int& A, int& B, int& C ) { int repA = 0, repB = 0, repC = 0; A = -1; // 三个初始值一定要不同,否则后续代码错误 B = -2; C = -3; for( int i = 0; i < count; ++i ) { if( arr[i] == A || repA == 0 ) A = arr[i], ++repA; else if( arr[i] == B || repB == 0 ) B = arr[i], ++repB; else if( arr[i] == C || repC == 0 ) C = arr[i], ++repC; else --repA, --repB, --repC; } }
总结:可以发现,遇到这类问题,每次提取出一些元素,尽量保证提取出元素后,剩下的还能维持原来的比例,这样就将问题规模缩小了,另外这种方法是O(n)时间复杂度的,可以说基本上是最优的解法了。好了,如果有人问你,一个数在无序数组中出现次数大于等于总数的2/5,找出这个数,你会做了吗?
相关文章推荐
- 数据结构面试题总结5——数组:找出数组中唯一一个出现一次的元素
- 【面试题】数组中有两个元素出现了奇数次,其他元素出现了偶数次。找出这两个元素
- 面试题精选(86):O(lgn)时间内找出有序数组中某个元素出现的次数
- 面试题:找出数组中出现次数超过一半的数
- 找出数组中出现奇数次的元素
- 找出数组里面元素出现次数最多的问题
- 每日一道算法题:微软面试题:在排序数组中,找出给定数字出现的次数
- 水贴王之续,找出数组里出现频率最高的元素
- 数组中至多有一个出现次数大于数组长度一半元素,找出这个元素
- 找出有序元素数组中指定元素出现的次数
- 面试题———关于将一个整型数组中的所有元素组合成一个数字,并找出最小一个。
- 找出数组里面元素出现次数最多的问题
- 整数数组中,每个元素均出现两次,除了一个元素例外,如何找出这个元素?能否设计一个线性时间的算法,且不需要额外的存储空间?
- leetcode-singleNum2 找出一个数组中只出现过一次的元素
- java找出一个数组中出现次数最多的那个元素
- 现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
- 程序员面试题精选100题(34)-找出数组中两个只出现一次的数字
- Single Number--找出数组中唯一的一个只出现一次的元素
- 一道面试题 有20个数组,每个有500个元素,升序排列,找出前500的数
- 找出一个数组中只出现过一次的元素