求数组中多于一半的或者是多于1/3的全部数字都可以用这种方法解决
这里给你一个数组,要你求出所有出现数量多于 ⌊
n/3
⌋
的数字,这题方法简单,但是原理非常复杂,,首先用两个数a,b,n1,n2来分别记录峰1,峰2,峰1的数量,峰2的数量,可以证明,当求 所有多于⌊ n/m ⌋的数的时候,只要定义(m-1)个不同的数字,以及(m-1)个不同的计数,将所有计数初始化为0,所有数字初始化为不同值,记住,一定要是不同值,但是可以是任何值,要不然不能保证计算过程中所有数字的不同,最后可能导致result里面添加多个相同的数字
证明方法是,当发现num[i]和a1,a2,…am-1里面一个数字相同的时候,假设是ak,将nk加一,当发现num[i]和任何一个数字都不同的时候,替换掉任何一个nk==0的数字,也就是ak=num[i],nk++,就这样一直计算下去,可以证明,当计算完成的时候,a1,a2…am-1里面一定存在所有出现次数多于⌊ n/m ⌋的数,这时只要重新检查a1,a2…am-1看那个出现的次数多于⌊ n/m ⌋就行了
这里简单的证明一下,假设有m个区间,每个区间有t个数,那么n可表示成n=m*t+z,这里z=0~m-1,这里假设有一组多于⌊ n/m ⌋,设这组为A,那么他的数量num(A)>=t+1,<=n,可以证明,每一个A里面的数可以和m-1个其他数消除,每m-1个其他数可以消除一个A,我们现在来证明当算法进行到最后A一定消除不完。
我们使A的数量最少,为t+1,非A的数尽可能的多,为(m-1)*t+m-1-1=n-t-1,非A的数能消耗A的数最多为⌊ (m-1)*t+m-1-1 ⌋=⌊ t-1/(m-1) ⌋<t+1,因此A的数最后一定有剩,A的数有剩则其一定存在于a1,a2…am-1里面,否则其一定被消耗完了,这和假设不符,其他各个多于⌊ n/m ⌋的数也可以同样证明,
class Solution {
public:
vector<int> majorityElement(vector<int>& nums) {
inta, n1, b, n2, num; vector<int> result;
num= nums.size() / 3;
n1= n2 = 0; a = 0; b = 1;
for(int u : nums)
{
if(u == a)
{
n1++;
}
else
if(u == b)
n2++;
else
if(n1==0)
{
a= u; n1++;
}
else
if(n2==0)
{
b= u; n2++;
}
else
{
n1--;n2--;
}
}
n1= 0; n2 = 0;
for(int u : nums)
{
if(u == a) n1++;
if(u == b) n2++;
}
if(n1 > num) result.push_back(a);
if(n2 > num) result.push_back(b);
returnresult;
}
};