栈模拟 woj Problem 1204 - 继续找相同

Time Limit: 1000MS  Memory Limit: 5240KB  Difficulty: 5 Total Submit: 2280 Accepted: 477 Special Judge: No
Description

有 n 个整数, 其中有且仅有一个整数出现了 >= n/2.0 次 (n<=500000)

Input
每组数据第一行是 n, 然后接下来一行是 n 个整数, 请读入到 EOF
Output
输出每行一个整数, 即要找的这个数
Sample Input
9
5 5 5 5 5 1 2 3 4
Sample Output
5

问题分析:
problem 1203:数据量很大,必须要用O(n)的算法。

可以证明,对于一个包含n个元素的数组,如果有一个数字出现的次数大于n/2那么从这个数组中拿走任意两个不同的数,那个数字出现的次数仍然超过(n-2)/2
那么只要设计一个算法,每次从中取出两个数字,如果相同,则留下,不同则都移除。如果数组中不再有不同的数,那么就找到它了。
考虑用栈stack来实现
按顺序处理每一个数字:
如果栈空,入栈;
如果栈不过空,比较栈顶元素与当前数字:
   如果相同,该数字入栈
   如果不同,栈顶元素出栈
处理完所有数字后,栈里剩下的数字必然是同一个数字,也就是要求的结果。

而本题要找的那个数可能正好是n/2次。
可以讨论一下可能的情况:
1. n是奇数,OK,其实就是1203。
2. n是偶数,好吧,再分情况
   1) 出现了 > n / 2次,OK,还是1203。
   2) 出现了正好 n / 2次:完蛋,按照1203去做,最后栈空了
           ——那最后一次咱就不出栈了,看看剩下的两个数哪个出现得多就OK了。但是直接发现用c++栈操作
会超时,尝试模拟栈后ac

代码:
/*=============================================================================
#     FileName: 1204.cpp
#         Desc: 
#       Author: JxGuo
#        Email: whu18707199852@gmail.com
#      Version: 1.0
#   LastChange: 2013-03-06 10:40:30
#      History:
=============================================================================*/
#include<stdio.h>
#include<stdlib.h>

int num[500005];

int main()
{
    int n;
    while(scanf("%d",&n) != EOF)
    {
        int i;
        int s1 = 0;
        int t2;
        int ans;
        for(i = 0; i < n; i++)
        {
            scanf("%d",&num[i]);
            if(s1 == 0)
            {
                s1++;
                ans = num[i];
            }
            else if(ans == num[i])
                s1++;
            else 
                s1--;
        }
        if(s1 > 0)
            printf("%d\n",ans);
        else
        {
            t2 = num[n-1];
            int i,num1 = 0, num2  = 0;
            for(i = 0; i < n; i++)
            {
                if(num[i] == ans)
                    num1++;
                else if(num[i] == t2)
                    num2++;
            }
            if(num1 > num2)
                printf("%d\n",ans);
            else
                printf("%d\n",t2);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值