前提:给出一个ID数组,其中每个ID都可能重复出现,其中一个ID的重复出现个数超过了数组长度的一半。
问题:要找出这个水王ID
要求:要求时间和空间代价最小
等价于:找出数组中元素过半的元素,要求时间和空间代价最小
扩展:
1、ID数组中,有三个水王ID,这三个水王ID重复出现的次数,都超过了数组长度的1/4。要求快速找到这3个水王ID。
2、ID数组中,有 K个水王ID,这K个水王ID重复出现的次数,都超过了列表长度的1/(k+1)。要求快速找到这K个水王ID。
~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~
前提:给出一个ID数组,其中每个ID都可能重复出现,其中一个ID的重复出现个数超过了数组长度的一半。
问题:要找出这个水王ID
要求:要求时间和空间代价最小
方法一:先对ID数组进行排序,再遍历排序后的序列,统计每个ID的次数,从而寻找到最大次数的ID。
时间复杂度 O(nlgn) + O(n) = O(nlgn)
不需要另外开辟空间
方法二:先对ID数组进行排序,水王的ID必然是数组中间那个
时间复杂度O(nlgn)+ O(1)= O(nlgn)
不需要另外开辟空间
方法三:不进行排序,而且把时间复杂度降到 O(n),即仅仅遍历一遍数组就找到
思路:每次删除两个不同的ID,最终得到那个ID就是我们要找的水帖ID
时间复杂度O(n) + 空间复杂度O(1)。
分析:由于水王ID的个数占ID数组长度一半以上, 即水王ID的总数会大于所有非水ID总数之和,因此,每次删除两个不同的id,无论删减顺序如何,最后超过一半以上的ID一定是不会被删减完的,也是唯一一个不会被删减掉的ID。通过这点,将不断重复这个过程,将ID数逐渐降低,最后就可以得出这个水ID。
一种最极端的状况就是,所有非水王ID都与水王ID抵消。但因为,水王发的帖占大于总帖数一半,故其水王发的贴 总数 减去 其他人发的所有帖子之和,总会大于0,所以最终返回的ID总会是水王的ID。
难点:
如何每次删除两个不同的ID:
可以使用CandidateID保存上一次遇到的ID,count为此ID在抵消后剩余的个数
如果遇到相同的ID,count++,表示有该CandidateID又出现一个,也即是有可以与不同的ID抵消一次
如果遇到不同的ID,count–,此时不做其他操作
也就表示,现在ID 和 CandidateID已经被抵消了,下次再处理时,要首先检查count值,如果count=0,表示刚刚候选CandidateID
已经抵消完,要重新为其赋值,此时的ID不是上次与CandidateID抵消的ID了,而是本次刚刚要处理的ID,此时就表示已经上一次ID
和candidateID抵消了
代码:
使用两个变量
CandidateID:保存候选水帖ID,初始化为第一个贴ID
count:保存该ID的和不同的ID抵消过后,剩余的次数
然后遍历ID列表,得到下一个待处理的ID,
如果当前CandidateID没有保存过ID 或 已经删减完(即ID对应次数为0),
那么保存待处理的ID,并且计数设置为1;
如果遇到的ID刚好是保存的CandidateID,
那么计数加1;
如果遇到的ID是一个新的ID,//候选ID 和 现在遇到的ID一起丢掉
那么ID的计数减1。
这样遍历之后,整个遍历下来,相同的ID都会被累加起来,而不同ID之间会互相抵消,最后剩下来的candidateID就是所求水王ID。
扩展:
1、ID数组中,有三个水王ID,这三个水王ID重复出现的次数,都超过了数组长度的1/4。要求快速找到这3个水王ID。
2、ID数组中,有 K个水王ID,这K个水王ID重复出现的次数,都超过了列表长度的1/(k+1)。要求快速找到这K个水王ID。
扩展1与扩展2的思路是一样的,只不过开辟的数组大小不同而已
思路:每一个水ID数总是大于所有非水ID的总数,思路是类似的,每次删除四个不同的ID,不影响” 那三个水ID在剩余ID中出现仍然查过1/4″这个事实。因此,我们可以每次删除四个不同的ID,直到剩余3个水ID为止
代码:
使用两个数组处理
用candidateID[3]记录三个候选ID
用count[3]记录它们的累积次数
然后遍历整个ID列表,每处理一个ID
若与candidateID[i]中的某一个相同,
则对应的count[i]++,
若与三个都不同,
将三个count[i]--
这样遍历之后,整个遍历下来,相同的ID都会被累加起来,而不同ID之间会互相抵消,最后剩下来的candidateID[i]就是所求
难点:
怎么体现“删除四个不同ID”这一动作
在处理一个ID时,都要与CandidateID[i]相比较,如果与CandidateID[i]中的数全都不一样是,就相当于找到了四个不同数,让三个count[i]都–,此时就可以表示,一次删除四个不同ID了。