剑指offer——题目:数组中有一个数字出现次数超过数组长度的一半,请找出这个数字。
方法1:利用qsort函数对数组进行排序,然后找出数组长度n的中位数n/2处的元素。判断其出现次数是否超过数组长度的一半。
在检查函数中,我设置的若出现次数没有超过数组长度的一半则返回-1。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int CheckNum(int a[],int len,int result)
{
int time = 0;
for (int i = 0; i < len; i++){
if (a[i] == result){
time++;
}
}
if (time * 2 <= len){
return -1;
}
return 1;
}
int int_cmp(const void * p1, const void * p2)
{
return (*(int *)p1 > *(int *)p2);
}
int main()
{
int arr[] = {1,3,3,2,2 };
int mid = 0;
int len = sizeof(arr) / sizeof(arr[0]);
int ret = 0;
qsort(arr, len, sizeof(int), int_cmp);
mid = arr[len / 2];
ret = CheckNum(arr, len, mid);
if (ret == -1){
printf("没有一个数字出现次数超过一半。\n");
}
else{
printf("%d\n", ret);
}
system("pause");
return 0;
}
方法2:数组中有一个数字出现次数超过数组长度一半,也就是说它的出现次数比其他数加起来还要多。我们可以在遍历数组时保存两个值:一个为数组元素,一个为次数。当我们遍历到下一个元素时,如果和前一个数字相同,次数加1;不同减1;如果次数为0,则保存下一个数字,次数重置为1。则要找的数字就是最后一次把次数设为1的数字。
这里也要检查所得数字是否出现次数超过数组长度一半。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int CheckNum(int a[],int len,int result)
{
int time = 0;
for (int i = 0; i < len; i++){
if (a[i] == result){
time++;
}
}
if (time * 2 <= len){
return -1;
}
return 1;
}
int FindNum(int a[], int len)
{
int time = 1;
int result = a[0];
for (int i = 0; i < len; i++){
if (0 == time){
result = a[i];
time = 1;
}
else if (result == a[i]){
time++;
}
else{
time--;
}
}
if (CheckNum(a, len, result) == -1){
return -1;
}
return result;
}
int main()
{
int arr[] = { 2, 4, 5, 8, 8, 8, 8, 1, 0, 2, 8, 8, 8 };
int len = sizeof(arr) / sizeof(arr[0]);
int ret = FindNum(arr, len );
if (ret == -1){
printf("没有一个数字出现次数超过一半。\n");
}
else{
printf("%d\n", ret);
}
system("pause");
return 0;
}