[九度][何海涛] 数组中出现次数超过一半的数字

题目描述:

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

 

输入:

每个测试案例包括2行:

第一行输入一个整数n(1<=n<=100000),表示数组中元素的个数。

第二行输入n个整数,表示数组中的每个元素,这n个整数的范围是[1,1000000000]。

 

输出:

对应每个测试案例,输出出现的次数超过数组长度的一半的数,如果没有输出-1。

 

样例输入:
9
1 2 3 2 2 2 5 4 2
样例输出:
2


这道题可以分两种方法做。方法1:类似于消除原理,既然某个数字大于长度的一半,那么我们就遍历数组,如果两个数不相等则消除,最后剩下的数就是我们要的。当然如果不存在这样的数,这是不行的。所以最后要再遍历一遍验证这个数的出现次数是否大于数组的一半。
 1 #include <iostream>
 2 using namespace std;
 3 
 4 bool check(int num[], int key, int n)
 5 {
 6     int count = 0;
 7     for(int i = 0; i < n; i++)
 8         count += (key == num[i]);
 9 
10     return 2 * count > n;
11 }
12 
13 int main()
14 {
15     int firstCount = 0;
16     int secondCount = 0;
17     int firstNum;
18     int secondNum;
19     int num[100000];
20 
21     int n;
22     while(cin >> n)
23     {
24         firstCount = 0;
25         secondCount = 0;
26         for(int i = 0; i < n; i++)
27         {
28             cin >> num[i];
29             if (firstCount > 0 && num[i] == firstNum)
30             {
31                 firstCount++;
32             }
33             else if (secondCount > 0 && num[i] == secondNum)
34             {
35                 secondCount++;
36             }
37             else if (firstCount == 0)
38             {
39                 firstNum = num[i];
40                 firstCount = 1;
41             }
42             else if (secondCount == 0)
43             {
44                 secondNum = num[i];
45                 secondCount = 1;
46             }
47             else
48             {
49                 int minCount = min(secondCount, firstCount);
50                 secondCount -= minCount;
51                 firstCount -= minCount;
52                 if (secondCount == 0)
53                 {
54                     secondNum = num[i];
55                     secondCount = 1;
56                 }
57                 else
58                 {
59                     firstNum = num[i];
60                     firstCount = 1;
61                 }
62             }
63         }
64 
65         int minV = min(firstCount, secondCount);
66         firstCount -= minV;
67         secondCount -= minV;
68 
69         if (firstCount > 0)
70         {
71             if (check(num, firstNum, n))
72                 cout << firstNum << endl;
73             else
74                 cout << -1 << endl;
75         }
76         else if (secondCount > 0)
77         {
78             if (check(num, secondNum, n))
79                 cout << secondNum << endl;
80             else
81                 cout << -1 << endl;
82         }
83         else
84             cout << -1 << endl;
85     }
86 }

方法2:用qsort的partition的方法找出第k大数,k就是数组中间的数,对于n为偶数是中间两个的任意一个数,奇数的话就只有一个。那么,因为数的个数超过一半,那么中间那个数肯定是超过一半的那个数,否则这个数就不存在了。最后遍历一遍数组来验证一下。partition的平摊复杂度为O(n)。最后算法总体复杂度O(n)

 1 #include <iostream>
 2 #include <ctime>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 void partition(int num[], int left, int right, int k)
 8 {
 9     if (left >= right)
10         return;
11 
12     int randNum = left + (rand() % (right - left + 1));
13 
14     int t = num[left];
15     num[left] = num[randNum];
16     num[randNum] = t;
17 
18     int i = left;
19     int j = right;
20 
21     int key = num[left];
22 
23     while(i <= j)
24     {
25         if (num[i] <= key)
26             i++;
27         else
28         {
29             int t = num[j];
30             num[j] = num[i];
31             num[i] = t;
32 
33             j--;
34         }
35     }
36 
37     num[left] = num[j];
38     num[j] = key;
39 
40     if (j == k)
41         return;
42     else
43     {
44         partition(num, left, j - 1, k);
45         partition(num, j + 1, right, k);
46     }
47 }
48 
49 int main()
50 {
51     int n;
52     int num[100000];
53 
54     while(cin >> n)
55     {
56         for(int i = 0; i < n; i++)
57             cin >> num[i];
58 
59         srand(time(NULL));
60         partition(num, 0, n - 1, n / 2);
61 
62         int key = num[n / 2];
63 
64         int count = 0;
65         for(int i = 0; i < n; i++)
66             count += (key == num[i]);
67 
68         if (2 * count > n)
69             cout << key << endl;
70         else
71             cout << -1 << endl;
72     }
73 }

 

posted @ 2012-11-22 10:58  chkkch  阅读(1426)  评论(0编辑  收藏  举报