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就是答案。

#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

 

posted on 2016-10-24 23:52  stupid_one  阅读(193)  评论(0编辑  收藏  举报

导航