http://ac.jobdu.com/problem.php?pid=1370
不错的题。O(n+k*log(n))过不了,O(n)可以过,有些人直接快排过了,这个似乎有点不太好
这道题两种思路:
(1)O(n+k*log(n)) 我的超时了,即使递归改为非递归也超时
思路:如果一个数出现次数超过总个数的一半,那么这个数的数值必然等于中位数的数值,因为如果排序的话,那么这个数必然会“包住”中数。下面是代码,注释掉的是递归版
#include <cstdio>
#include <cstring>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int SIZE = 100000+1;
int num[SIZE];
int n;
int Partition(int num[], int st, int en){
int pivort = num[st];
while(st < en){
while(st < en && num[en] >= pivort)en--;
num[st] = num[en];
while(st < en && num[st] <= pivort)st++;
num[en] = num[st];
}
num[st] = pivort;
return st;
}
/*int findMid(int num[], int st, int en, int p){
if(st <= en){
int pos = Partition(num, st, en);
if(pos == p){
//cout << "pos=" << p << " " << num[p] << endl;
return num[p];
}
if(pos > p){
return findMid(num, st, pos-1, p);
}
if(pos < p){
return findMid(num, pos+1, en, p);
}
}
}*/
int flag;
int findMid(int num[], int st, int en, int p){
int pos;
while(st <= en ){
flag=1;
pos = Partition(num, st, en);
if(pos == p){
return num[p];
}
if(pos > p){
en = pos -1;
//pos = Partition(num, st, en);
}
if(pos < p){
st = pos +1;
//pos = Partition(num, st, en);
}
}
flag=0;
return num[0];
}
int main(){
while(~scanf("%d",&n)){
flag=0;
for(int i=0;i<n;i++){
scanf("%d", &num[i]);
}
int c = findMid(num,0,n-1,n/2);
if(flag == 0){
printf("-1\n");
continue;
}
int cnt=0;
for(int i=0;i<n;i++){
if(num[i] == c){
cnt++;
}
if(cnt*2 > n)break;
}
if(cnt*2 > n)
printf("%d\n",c);
else
printf("-1\n");
}
return 0;
}
(2)正确思路O(n) 要求的数出现的次数比其他数出现的次数的总和还多。
有一个很好的性质,如果当前还没有找到一个数,比遇到的其他数出现的次数总和还多,那么后面肯定有。额,说的混乱了,看代码:
#include <cstdio>
#include <cstring>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int SIZE = 100000+1;
int num[SIZE];
int n;
bool check(int c){
int cnt=0;
for(int i=0;i<n;i++){
if(num[i] == c)cnt++;
if(cnt*2 > n)return true;
}
return false;
}
int solve(){
int c = num[0];
int cnt =1;
for(int i=1;i<n;i++){
if(num[i] == c){
cnt++;
}else{
cnt--;
}
if(cnt == 0){
c = num[i];
cnt = 1;
}
}
if(check(c))return c;
else return -1;
}
int main(){
while(~scanf("%d", &n)){
for(int i=0;i<n;i++){
scanf("%d", &num[i]);
}
printf("%d\n",solve());
}
return 0;
}