九度oj 特殊的数字

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:05   1365   0

题目描述:

现在有n个数,其中有一些出现了一次,一些出现了两次,一些出现了很多次。现在要求你找出那些只出现一次的数,并按升序输出。

输入:

本题有多组case。

每个case有两行,第一行输入一个n,表示有n个数,1<= n <= 1000000。

第二行有n个数字。每个数字的大小范围[1, 1000000]。

输出:

每次输出有两行。

第一行输出一个整数,表示出现一次的数的个数。

第二行按升序输出出现次数为一次的数字,两个数字之间用空格隔开。

样例输入:
5
1 2 2 3 3
7
1 2 2 3 4 4 2
2
2 2
样例输出:
1
1
2
1 3
0

分析:由于题目限定了所能用的空间,所以要使用位压缩。开一个char数组,大小为MAX/8,表示用一个二进制位存一个数字的状态:1:表示该数字只出现了一次,0:表示与1相反的情况:

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
const int M=1010;
const int N=100010;
int n;
char hash[N/8],vis[N/8];
int main()
{
    int i,j;
    while(~scanf("%d",&n))
    {
        memset(hash,0,sizeof(hash));
        memset(vis,0,sizeof(vis));
        int value,index,sum=0,minn=1000100,maxx=-1;
        for (j=0;j<n;j++)
        {
            scanf("%d",&value);
            if (maxx<value) maxx=value;
            if (minn>value) minn=value;
            index=value>>3;   // value应存放在hash[]里的位置下标
            value&=7;  //  value 在字符中二进制位置
            if (!(hash[index] & 1<<value)) { hash[index]|=1<<value; sum++;} // value 没有出现过
            else if (!(vis[index] & 1<<value)) {  // value 第二次出现
                vis[index]|=1<<value; //  用vis数组标记
                sum--;  // 合法解总数减一
            }
        }
        int k=0;
        if (sum){
            printf("%d\n",sum);
            for (i=minn;i<=maxx;i++) {
                index=i>>3;
                int e=i;
                i&=7;
                if (hash[index] & 1<<i && !(vis[index] & 1<<i)){
                    if (k<sum-1) printf("%d ",e);
                    else printf("%d\n",e);
                    k++;
                }
                i=e;
            }
        }
        else cout<<0<<endl;
    }
}


















分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP