《编程之美》第2.3节:寻找发帖水王
题目一:给定一个数组,共有N个数,其中有一个数出现了超过N/2次,用O(N)的时间找出这个数。
解法:不断从数组中删除2个不同的数,这个时候,要求的数仍然占据总数的1/2以上。
题目二:给定一个数组,共有N个数,其中有3个数出现了超过1/4次,用O(N)的时间找出这3个数。
解法:同上,不断从数组中删除4个不同的数即可。
#include<iostream>
using namespace std;
int find(int ID[],int N)
{
int candidate=0;
int nTimes=0;
for(int i=0;i<N;i++)
{
if(nTimes==0)
{
candidate=ID[i];
nTimes=1;
}
else
{
if(candidate==ID[i])
nTimes++;
else
nTimes--;
}
}
return candidate;
}
int* find3(int ID[],int N)
{
int *candidate=new int[3];
for(int i=0;i<3;i++)
candidate[i]=0;
int nTimes[3]={0};
for(int i=0;i<N;i++)
{
if(nTimes[0]==0 || candidate[0]==ID[i])
{
candidate[0]=ID[i];
nTimes[0]++;
}
else if(nTimes[1]==0 || candidate[1]==ID[i])
{
candidate[1]=ID[i];
nTimes[1]++;
}
else if(nTimes[2]==0 || candidate[2]==ID[i])
{
candidate[2]=ID[i];
nTimes[2]++;
}
else
{
if(candidate[0]==ID[i])
nTimes[0]++;
else if(candidate[1]==ID[i])
nTimes[1]++;
else if(candidate[2]==ID[i])
nTimes[2]++;
else
{
nTimes[0]--;
nTimes[1]--;
nTimes[2]--;
}
}
}
return candidate;//如果要返回指针,则必须要用new开辟,否则当函数返回则这个栈中数据会被弹出
}
int main()
{
const int N=10;
int ID[N]={1,1,1,1,2,3,4,4,1,1};
cout<<find(ID,N)<<endl;
int ID3[N]={1,1,1,2,2,2,3,3,3,5};
int *p=find3(ID3,N);
for(int i=0;i<3;i++)
cout<<*(p+i)<<endl;//注意这里一定不能用*p++,否则后面的delete []p会出错
delete []p;
system("pause");
return 0;
}
注意返回的指针,一般返回结构体,或者vector更好,这里用指针一定要注意必须是new出来的数据,否则在函数返回后,函数内部在栈中的数据都会出站,这样就会导致不确定的因素。
注意要delete []p时,p不能改变,否则会出错。