求数组中次数超过一半的数字

来源:互联网 发布:国家数据 编辑:程序博客网 时间:2024/06/06 13:58

一个数组中有一个数字的次数超过了数组的一半,求出这个数字。

如:int a[]={2,3,2,2,2,2,2,5,4,1,2,3},求出超过一半的数字是2。

这个问题有两种解法,第一种是依靠数组的特点来找出这个数,第二种是利用排序的思想来找,下面依次介绍这两种方法。

1.利用数组本身的特性

题目给出这个数出现的次数超过了数组元素个数的一半,假设数组为a[n],如果用计数的方法来依次记录该数出现的次数则为>n/2,而其它所有的元素出现的次数总和则<n/2。假设我们把a[0]默认为要找的数,次数times设置为1,然后再与剩下的元素进行判断,如果与要找的数相同,则times+1,不同,则times-1。如果times为零,则恰好说明要找的数与其它数出现的次数相等,则将下一个数重新设置为默认的数即可。所以,要找的数肯定是最后一次把times置为1的数。

int FindHalfNum1(int* a, int size){//判断数组是否合法if (a == NULL || size <= 0){return 0;}int result = a[0];int times = 1;for (int i = 0; i < size; i++){if (times == 0){result = a[i];}else if (a[i] == result){times++;}else{times--;}}int count = 0;for (int i = 0; i < size; i++){if (a[i] == result){count++;}}//判断所找到的数出现的次数是否符合题目的要求if (count * 2 >= size){return result;}else{return 0;}}
2.基于排序思想

如果给的数组是有序的,那么只要统计出每个数字出现的次数,就可以找出该数。如果数组是有序,那么数组的中位数一定就是我们要找的数,因为该数出现的次数超过了数组元素个数的一半,所以从统计学的角度出发,该数必然会出现在中位数的位置mid上。那么问题就转化为如何在无序的数组中找出中位数,可以借鉴快速排序的思想,随机拿到数组中的一个数x,调整数组中元素的位置,保证x左边的数都不大于它,右边的数都不小于它,再递归排序就是快排。而我们要找的中位数只要将x的下标与mid进行比较,就像二分法那样,不断缩小范围,每次只对一段区间进行元素调整,就可以找出中位数,即题目要求的数。

int GetMedian(int* a, int size, int start, int end){if (a == NULL || size <= 0 || start < 0 || end >= size){throw new exception("Invalid parameters");}int k = end;while (start < end){while (start < end && a[start] <= a[k]){start++;}while (start < end && a[end] >= a[k]){end--;}if (start < end){swap(a[start], a[end]);}}swap(a[start], a[k]);return start;}int FindHalfNum2(int* a, int size){if (a == NULL || size <= 0){return 0;}int start = 0;int end = size - 1;int mid = size >> 1;int index = GetMedian(a, size, start, end);while (index != mid){if (index < mid){start = index + 1;index = GetMedian(a, size, start, end);}else{end = index - 1;index = GetMedian(a, size, start, end);}}}


原创粉丝点击