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

题目描述:数组中有一个数字的个数超过数组长度的一半,请找出这个数字。例如一个长度为9的数组{1, 2, 3, 2, 2, 2, 5, 4, 2}中数字2出现了两次,所以输出2.

算法描述:

  解决这道题有几种方法。

  (1)对数组进行排序,然后选取数组的中位数即可,但是我们知道排序最好的最好的时间复杂度就是O(nlgn)。

  (2)下面两种方法是在O(n)的时间内实现的:

    1)基于Partition算法的实现;

      我们知道在排序算法中有一种快速排序就是利用这种方法实现的。它的基本思想是:首先随机找到一个数字,调整数组中数字的顺序,让比这个数字小的数字排在它的左边,比它                  大的排在它的右边;如果下标正好是n/2.则查找成功;如果下标在n/2的左边,则查找它的右边;如果下标在n/2的右边则查找它的左边;递归进行即可;

    

    2)我们知道数组中有一个数字出现的次数超过一半,那么我们可以基于消除的思想去寻找这个数字。如果出现两个不一样的数字那么我们就将两个数字同时消去,继续向下寻找,知道                 最后,剩下的数字就是我们要找的数字。但这是基本的想法,代码实现有自己的思路;

算法实现:

O(n)算法1:基于partition

 1 #include<iostream>
 2 using namespace std;
 3  
 4 void swap( int &a, int &b){
 5     int temp = a;
 6     a = b;
 7     b = temp; 
 8 } 
 9 
10 int partition(int *data, int length, int start, int end){
11     if(data == NULL || length < 0 || start < 0){
12         cout<<"the invalid array";
13     }
14     
15     int temp = data[start];
16     int pos = start;
17     
18     for(int i = start + 1; i < end; i++){
19         if(temp >= data[i]){
20             ++pos;
21             swap(data[pos], data[i]);
22         }
23     }
24     
25     swap(data[start], data[pos]);
26     return pos;
27 }
28 
29 int MoreHalf(int *data, int length){
30     if(data == NULL || length < 0){
31         return 0;
32     }
33     
34     int mid = length >> 1;
35     int start = 0;
36     int end = length - 1;
37     int index = partition(data, length, start, end);
38     
39     while(index != mid){
40         if(index > mid){
41             end = index - 1;
42             index = partition(data, length, start, end);
43         }
44         else{
45             start = index + 1;
46             index = partition(data, length, start, end);
47         }
48     }
49     
50     return data[mid];    
51 } 
52 
53 int main(){
54     int str[] = {1, 2, 3, 2, 2, 2, 5, 4, 2};
55     int len = sizeof(str) / sizeof(int);
56     int num = MoreHalf(str, len);
57     
58     if(num == -1){
59         cout<<"wrong"<<endl;
60     }
61     else{
62         cout<<"the more than half value of str is: "<<num<<endl;
63     }
64     
65     return 0;
66 }

 算法2:

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int MoreHalf(int *data, int length){
 5     if(data == NULL || length < 0){
 6         return 0;
 7     }
 8     
 9     int result = data[0];
10     int times = 1;
11     for(int i = 1; i < length; ++i){
12         if(times == 0){
13             result = data[i];
14             times == 1;
15         }
16         else if(data[i] == result){
17             times ++;
18         }
19         else{
20             times--;
21         }
22     }
23     
24     return result;
25 }
26 
27 int main(){
28     int str[] = {1, 2, 3, 2, 2, 2, 5, 4, 2};
29     int len = sizeof(str) / sizeof(int);
30     int num = MoreHalf(str, len);
31     
32     if(num == -1){
33         cout<<"wrong"<<endl;
34     }
35     else{
36         cout<<"the more than half value of str is: "<<num<<endl;
37     }
38     
39     return 0;
40 }

参考书籍:

《剑指offer》

原文地址:https://www.cnblogs.com/dormant/p/5395381.html