题目描述:数组中有一个数字的个数超过数组长度的一半,请找出这个数字。例如一个长度为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》