0
点赞
收藏
分享

微信扫一扫

HDU 1029 一道微软面试题

​​http://acm.hdu.edu.cn/showproblem.php?pid=1029​​

给定一个数组,其中有一个相同的数字是出现了大于等于(n + 1) / 2次的。要求找出来、

1、明显排序后,中间那个位置的就是ans,复杂度O(nlogn)

2、

考虑分治

假设那个人是ans,那么对于其他人,我都用一个ans去代替它。就是他们两个一起死了,从这个数组中删除。

那么我最后剩下的那个人当然还是ans,因为它人数都大于一半了。

同时删除了两个没关的人,那更好了。如果枚举的那两个人都是ans,那么只能记录次数++,

关键是如何模拟这个过程。能做到O(n)的复杂度。

 

考虑用ans和anstime表示答案和答案那个人出现的次数。

1、如果anstime==0,就是还没确定谁是ans,那么就选当前这个人作为答案。

2、否则,如果当前枚举的这个人还是ans,那么记录次数+1,否则记录次数-1(大家一起死了)

最后ans就是答案。

HDU 1029 一道微软面试题_分治法

HDU 1029 一道微软面试题_分治法_02

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e6 + 20;
LL a[maxn];
int n;
void work() {
for (int i = 1; i <= n; ++i) {
scanf("%I64d", &a[i]);
}
LL ans = 0, anstime = 0;
for (int i = 1; i <= n; ++i) {
if (anstime == 0) {
ans = a[i];
anstime++; //出现了一次
} else {
if (ans == a[i]) { //同一个人的话,出现次数++
anstime++;
} else anstime--; //否则同时删除这两个人
}
}
printf("%d\n", ans);
}

int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
while (scanf("%d", &n) != EOF) work();
return 0;
}

View Code

 

举报

相关推荐

0 条评论