• 首师大附中互测题:99999999海岛帝国后传:算法大会【D001】


    【D001】99999999海岛帝国后传:算法大会【难度:D】

    ——————————————————————————————————————————————————————————————————————————————————————

    【题目要求】

     YSF经过百般思考后,决定召开一个“煽风点火”,来召集全世界优秀的计算机人士。算法大会只有一道题,是WXJ && LJX合力编写、研究出来的算法设计精品:(以下为YSF的发言稿)

        大家还记得这样一道超水,水的不能再水的题吗?(当然不是A+B问题啦)题目如上。

        总体说,就是高效实现。

        保证有且只有一个数符合条件。

    【输入输出及要求】如图(阅读者:真懒QAQ)

    【其它要求】

     运行时间限制:50ms

     n<=10^10,享受痛苦吧!

    【试题分析】50ms达到10^10我想问的是出题者你在逗我吗?通过度娘我发现这是一个著名的主元素问题,主要思想就是通过代码选出最有可能当选的人也就是候选人。既然如此可以得到这  样的一个结论:在元素数组中,删去不同的两个元素,数组的主元素保持不变。按照这样的思路,我们可以不断缩小问题的规模,最终使问题得解:
     设置变量Seed用于存储当前候选元素,初始化为数组首元素a[0];
     设置变量count用于控制候选元素,初始化为1;
     从第二个元素a[1]开始遍历数组,并与Seed相比较:相同,则count加1,读入下一个元素;
     不同,则count减1,读入下一个元素:相当于删去两个不同元素,缩小问题规模;如果count小于0则Seed不是主元素候选,读入下一个元素,count加1。
     这样一次遍历之后,得到的Seed就是主元素的候选;但因为最终得到的Seed元素有可能是序列最末位的两个元素之一,所以还需要验证。我们再次遍历数组,得到Seed出现的次数,与总数的一半比较来验证。

     总的来说这个方法的效率非常高可以达到比O(n)还好。所以,完美解决。哼(ˉ(∞)ˉ)唧

    【代码】

    #include <iostream>
    using namespace std;
    
    int MajorityElement( int *a, int n)
    {
    	int k, i;
    	int elem;
    	k = 1;
    	elem = a[0];
    	for( i = 1; i <n; i++ )
    	{
    		if( a[i]==elem ) k++;
    		else
    		{
    			k--;
    			if( k == 0 ) { k = 1; elem = a[i]; }
    		}
    	}
    	return elem;
    }
    int main(int argc, char* argv[])
    {
    	int n;
    	cin>>n;
    	int a[n];
    	for(int i=1;i<n+1;i++) cin>>a[i];
    	cout<<MajorityElement(a,sizeof(a)/sizeof(a[0]))<<endl;
    }
    
  • 相关阅读:
    编程之美---求数组中最长递增子序列
    编程之美----子数组的最大乘积
    编程之美----寻找数组中的最大值和最小值
    编程之美---找符合条件的整数
    编程之美----最大公约数问题
    编程之美----1的数目
    编程之美----寻找发帖“水王”
    C语言 |= &= 位运算
    整型数类型定义
    extern使用方法总结!(转)
  • 原文地址:https://www.cnblogs.com/lijiaxin-blog-cpp/p/5606218.html
Copyright © 2020-2023  润新知