WOJ-204 继续找相同

一、实验目的及要求

1)实验问题:有 n 个整数, 其中有且仅有一个整数出现了 >= n/2.0 次 (n<=500000),通过代码来找到这个整数。
2)输入:每组数据第一行是 n, 然后接下来一行是 n 个整数, 请读入到 EOF
3)输出:输出每行一个整数, 即要找的这个数

二、实验设备(环境)及要求

代码撰写与本地调试:Windows10系统下的VSCode
代码调试:WOJ平台 Ubuntu Linux 16.04 LTS 64bit
要求与限制:
内存默认限制为512MiB,栈空间为512MiB(即不限制)。所有网络访问、非法系统调用被直接忽略,而不是返回Runtime Error。Java、Python与C#的时限已经按比例缩放,评测结果中的时间是进行缩放之后的时间

三、实验内容与步骤

1.处理输入
处理输入的整数个数n;

int main()
{
    int n;
    while(scanf("%d",&n) != EOF)
{
...
}
return 0;
}

处理接下来输入的n个整数;

for(i = 0; i < n; i++)
        {
            scanf("%d",&num[i]);
            ......
        }

2.当这个整数出现次数 > n/2.0次 时

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--;
        }

采用的是边输入边处理的方案,其思路类似于堆栈处理,只不过没有构造明显的栈进行操作,而是使用了一个变量s1来模拟栈。
变量s1初始化为0。当收到第一个输入时,将s1置为1,并记录第一个输入到变量ans中。之后的每一个输入,先与ans进行比较,如果等于ans则s1加1,如果不等于ans则s1减1.在这里,加1的操作类似于元素进栈,减1的操作类似于元素出栈。当栈中为空(s10)时,重新取得当前的ans。
但是这种构造方式对一种输入情况会出现特殊结果:
//input : 3 1 2 1
//output: 2
这个具体是因为什么呢?在这种正确答案以隔一个出现一次的情况下,最终的结果就会出现错误。其实都不需要严格的隔一个出现一次,只需要最后两个输入的数字不相同,并且应该正确输出的那个数字处在最后一位,并且这个数字的出现次数
n/2.0即可,也即(4 1 2 2 1 1 2 1)这样的输入也会导致答案错误。
知道了这个特殊例子我们就进行特殊处理。在上述情况中,在要输出答案的时候,s1这个变量的值一定是为0的。所以我们增加一个判定条件:

        if(s1 > 0)
            printf("%d\n",ans);
        //特殊情况! 
        else
        {
            int ans2;
            ans2 = num[n-1];
            int i,num1 = 0, num2  = 0;
            for(i = 0; i < n; i++)
            {
                if(num[i] == ans)
                    num1++;
                else if(num[i] == ans2)
                    num2++;
            }
            if(num1 > num2)
                printf("%d\n",ans);
            else
                printf("%d\n",ans2);
        }

在这里的特殊情况就对应着我们刚刚描述的情况。这种特殊情况我们只需要对输入的所以数字的最后两个数字进行一次遍历即可。

四、实验结果与数据处理
实验结果:

//input : 4
//input : 1 2 2 3
2
//input : 9
//input : 5 5 5 5 5 1 2 3 4
5

五、分析与讨论
这道题相对来说思路有些特别,由于之前没有做过类似的题目,刚拿到题目的时候我第一反应是进行排序。但在这道题之前已经有了203-找相同、202-找不同,其中题号为203的题目和这道题只差一个判别条件,而之前那道题用排序的方法会导致超时。之后我又想用我做203题的方法,就是构造一个很大很大的数组,用空间来换时间。不过这道题之所谓能作为5分难度,可能也是因为他的测试数据比较严格。使用大数组的方法在这道题也行不通。最后参考类似题目的栈方法,稍微改进了一点点,变成了现在的方法。

附代码

#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
        {
        	int ans2;
            ans2 = num[n-1];
            int i,num1 = 0, num2  = 0;
            for(i = 0; i < n; i++)
            {
                if(num[i] == ans)
                    num1++;
                else if(num[i] == ans2)
                    num2++;
            }
            if(num1 > num2)
                printf("%d\n",ans);
            else
                printf("%d\n",ans2);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/HizT_1999/article/details/106951147
204