问题简要描述:在数据集中,如何很快地找到超过数据集半数的数。
example:
input: 2 3 2 4 2 6 2 3 2 2
processing:..........
result: 2
分析一:利用排序算法,将数据进行排序,然后数据集中间的元素即为所求:
上述数据排完序后:2 2 2 2 2 2 3 3 4 6
中间的元素为: 2
时间复杂度仅与快速排序的时间复杂度有关。
代码实现:(排序算法选用快速排序法)
int findHalf_methodTwo(int *arr,int begin,int end){
quickSort(arr,begin,end);
return arr[(begin + end - 1)/2];
}
void quickSort(int *arr, int begin, int end){
if(begin >= end) return;
// 获取上一次排序枢轴位置(即就是 排序位置确定的元素位置)
int index = getIndex( arr, begin, end);
//对枢轴左边的数据进行递归排序
quickSort( arr, begin, index - 1);
//对枢轴右边的数据进行递归排序
quickSort( arr, index + 1, end);
}
int getIndex(int *arr, int low, int high){
int temp = arr[low];
while(low < high){
// 从最右端开始向左找到小于枢轴的元素
while(low < high && arr[high] >= temp) high --;
arr[low] = arr[high];//将 high指针 指向的小于枢轴的元素交换到 low指针 所指的位置
// 从最右端开始想右找到大于枢轴的元素
while(low < high && arr[low] <= temp) low ++;
arr[high] = arr[low];//将 low指针 指向的大于枢轴的元素交换到 high指针 所指的位置
}
arr[low] = temp;
return low;
}
分析二:每次删除两个不同的数,剩下的数据集中,原数据集过半的元素依然是新数据集中过半的元素,利用这个规律。
需要一个变量记录当前扫描的元素值;一个变量记录在扫描过程中,删除了两个不同的数后,剩下相同数的个数。
注意count的变化与数据的关系。
代码实现:
int findHalf_methodOne(int *arr,int N){
int temp;// 候选代号
int count;// 相同数的个数
for(int i = count = 0;i < N; i ++){
if(count == 0){
temp = arr[i];
count = 1;
}else{
if(temp == arr[i])
count ++;
else
count --;
}
}
return temp;
}
附:
整个程序代码:
#include <iostream>
#include <cstdio>
using namespace std;
void quickSort(int *arr, int begin, int end);
int getIndex(int *arr, int low, int high);
void show(int *arr, int N){
for(int i = 0;i < N;i ++)
cout<<arr[i]<<" ";
cout<<endl;
}
int findHalf_methodOne(int *arr,int N);
int findHalf_methodTwo(int *arr,int begin,int end);
int main(void){
int arr[10] = {2,3,2,4,2,6,2,3,2,2};
cout<<"the array:"<<endl;
show(arr, 10);
cout<<endl<<endl;
cout<<"the number of taking up half of all:"<<endl;
cout<<"method one:"<<findHalf_methodOne(arr,10)<<endl;
cout<<"method two:"<<findHalf_methodTwo(arr,0,9)<<endl;
return 0;
}
int findHalf_methodOne(int *arr,int N){
int temp;// 候选代号
int count;// 相同数的个数
for(int i = count = 0;i < N; i ++){
if(count == 0){
temp = arr[i];
count = 1;
}else{
if(temp == arr[i])
count ++;
else
count --;
}
}
return temp;
}
int findHalf_methodTwo(int *arr,int begin,int end){
quickSort(arr,begin,end);
return arr[(begin + end - 1)/2];
}
void quickSort(int *arr, int begin, int end){
if(begin >= end) return;
// 获取上一次排序枢轴位置(即就是 排序位置确定的元素位置)
int index = getIndex( arr, begin, end);
//对枢轴左边的数据进行递归排序
quickSort( arr, begin, index - 1);
//对枢轴右边的数据进行递归排序
quickSort( arr, index + 1, end);
}
int getIndex(int *arr, int low, int high){
int temp = arr[low];
while(low < high){
// 从最右端开始向左找到小于枢轴的元素
while(low < high && arr[high] >= temp) high --;
arr[low] = arr[high];//将 high指针 指向的小于枢轴的元素交换到 low指针 所指的位置
// 从最右端开始想右找到大于枢轴的元素
while(low < high && arr[low] <= temp) low ++;
arr[high] = arr[low];//将 low指针 指向的大于枢轴的元素交换到 high指针 所指的位置
}
arr[low] = temp;
return low;
}
运行结果: