您的位置:首页 > 其它

数组中出现次数超过一半的数字

2016-06-23 10:01 183 查看
题目:数组中有一个数字出现超过数组长度的一半,请找出这个数字。列入输入一个长度为9的数组{1,2,3,2,2,2,5,4,2},由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。 看到题目的第一感觉就是要先把未排序的数组排序,排序的最小时间复杂度(快速排序) O(N*logN) , 加上遍历,时间复杂度为: O(N*logN+N) 第二种方法是考虑每次删除两个不同的数,那么在剩下的数中,出现的次数仍然超过总数的一半。通过不断重复这个过程,不断排除掉其它的数,最终找到那个出现次数超过一半的数字。这个方法,免去了上述思路一、二的排序,也避免了思路三空间O(N)的开销,总得说来,时间复杂度只有O(N),空间复杂度为O(1),不失为最佳方法。 还有就是可以利用哈希表。如果所选的数组的元素比较集中的话可以使用哈希表统计每个元素出现的次数,时间复杂度是O(N),但是题目并没有给出数组元素的范围。次方法也不太好。有了上面的思路后,我们不难写出这样实现代码: 方法一:使用快排的思想实现
int Partition(int A[],int low,int high)
{
int pivot=A[low];
while(low <high)
{
while(low<high && A[high]>=pivot) --high;
A[low]=A[high];
while(low<high && A[low]<=pivot) ++low;
A[high]=A[low];
}
A[low]=pivot;
return low;
}
int HalfData(int a[],int len)
{
int start=0;
int end=len-1;
int middle=len >> 1;
int index=Partition(a,start,end);
printf("index1:%d\n",index);
while(index != middle)
{
if(index > middle)
{
end=index-1;
index=Partition(a,start,end);
}
else
{
start=index+1;
index=Partition(a,start,end);
}
}
return a[index];
}


方法二:遍历数组时保存两个值,一个是数组中的数字,另一个是次数,当遍历到下一个数字时,如果下一个数字与之前保存的数字相同,则次数加1,如果不同,则次数减1,如果次数为0,则需要保存下一个数字,并把次数设定为1。由于我们要找的数字出现的次数比其他所有数字的出现次数之和还要大,则要找的数字肯定是组后一次把次数设为1时对应的数字。该方法的时间复杂度为O(n),空间复杂度为O(1)。
int MoreThanHalfNum(int* numbers, unsigned int length)
{
if(numbers == NULL && length == 0)
{
g_bInputInvalid = true;
return 0;
}

g_bInputInvalid = false;

int result = numbers[0];
int times = 1;
for(int i = 1; i < length; ++i)
{
if(times == 0)
{
result = numbers[i];
times = 1;
}
else if(numbers[i] == result)
times++;
else
times--;
}

times = 0;
for(int i = 0; i < length; ++i)
{
if(numbers[i] == result)
times++;
}

if(times * 2 <= length)
{
g_bInputInvalid = true;
result = 0;
}

return result;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  空间 统计 元素