问题1:已知数组中有个元素出现的次数超过数组长度的一半,请找出这个数字。
设定这个元素为X,其他元素为A、B等
当遇到XX时,X、X都保留,占比不会变
当遇到AA时,A、A都保留,占比不会变
当遇到XA时,X、A都删除,占比会变高
当遇到AB时,A、B都删除,占比会变高这样对拼留到最后的一定是X
int findHlaf(int a[], int N)
{
int sum2 = 0;
int candidate;
int i;
for(i = 0;i < N; i++)
{
if(sum2 == 0)
{
candidate = a[i];
sum2++;
}
else
{
if(a[i] == candidate)
sum2++;
else
sum2--;
}
}
return candidate;
}
问题2:已知数组中有个元素出现的次数刚好是数组长度的一半,请找出这个数字。
根据题目描述可知,数组长度一定是偶数,因为奇数长度的数组不可能出现一个元素刚好占一半的情况。我们已经知道如何找元素出现次数超过一半的情况,那么我们将问题向它靠近。
取数组的最后一个数,它有两种情况,其一就是它刚好是这个占一半的元素,其二就是它不是。
1、如果它刚好是我们要找的元素,那么前面一定就有N/2-1个元素和它相等
2、如果它不是我们要找的元素,那么将最后一个数排除得到的剩下的N-1个数中,这个元素的占比就超过一半了,问题转化为上面的问题1。
代码如下:
int findHlaf(int a[], int N)
{
int sum1 = 0;//最后一个元素的个数
int sum2 = 0;
int candidate;
int i;
for(i = 0; i < N-1; i++)//扫描前N-1个元素
{
if(a[i] == a[N-1])//判断当前元素与最后一个是否相等
sum1++;
if(sum2 == 0)
{
candidate = a[i];
sum2++;
}
else
{
if(a[i] == candidate)
sum2++;
else
sum2--;
}
}
if((sum1 + 1) == N/2)
return a[N-1];
else
return candidate;
}
问题3:数组中如果有个元素出现的次数超过数组长度的一半,就返回这个数字,否则就返回0。
(假设数组的元素都不为0)
int findHlaf(int a[], int N)
{
int sum2 = 0;
int candidate;
int i;
for(i = 0; i < N; ++i)
{
if(sum2 == 0)
{
candidate = a[i];
sum2++;
}
else
{
if(a[i] == candidate)
sum2++;
else
sum2--;
}
}
if(sum2 > N/2)
return candidate;
sum2 = 0;
for(i = 0; i < N; ++i)
{
if(candidate == a[i])
sum2++;
}
if(sum2 > N/2)
return candidate;
return 0;
}
问题4:数组中如果有个元素出现的次数刚好数组长度的一半,就返回这个数字,否则就返回0。(假设数组的元素都不为0)
int findHlaf(int a[], int N)
{
if (N%2 == 1) //长度必须是偶数才能出现刚好一半的情况
return 0;
int sum1 = 0;//最后一个元素的个数
int sum2 = 0;
int candidate;
int i;
for(i = 0; i < N-1; i++)//扫描前N-1个元素
{
if(a[i] == a[N-1])//判断当前元素与最后一个是否相等
sum1++;
if(sum2 == 0)
{
candidate = a[i];
sum2++;
}
else
{
if(a[i] == candidate)
sum2++;
else
sum2--;
}
}
if((sum1 + 1) == N/2)
return a[N-1];
else
{
sum2 = 0;
for(i = 0; i < N; ++i)
{
if(candidate == a[i])
sum2++;
}
if(sum2 == N/2)
return candidate;
return 0;
}
}