九度笔记之 1351:数组中只出现一次的数字

题目1351:数组中只出现一次的数字

1 秒

内存限制:32 兆

特殊判题:

提交:1139

解决:314

题目描述:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
输入:
每个测试案例包括两行:
第一行包含一个整数n,表示数组大小。2<=n <= 10^6。
第二行包含n个整数,表示数组元素,元素均为int。
输出:
对应每个测试案例,输出数组中只出现一次的两个数。输出的数字从小到大的顺序。
样例输入:
8
2 4 3 6 3 2 5 5
样例输出:
4 6

算法分析

         假设a,b为数组中只出现了一次的两个数,

         由于相同的两个数进行 按位异或 运算得到 0, 而0 和任何数值进行 按位异或 得到该数本身。

         对数组中所有数值进行异或运算,而a,b两数只出现了一次,那么最终的结果等于 a按位异或b,得到andr

         可知andr上必有一位为1,并且 a,b两数在该位上不同(否者 按位异或后就得0)。

         我们根据andr上该1位对数组中的所有数值进行分类,该位为1的为1组,为0的为1组。

         这样就转化为了 一个数组只有一个数出现一次,其它数出现两次的问题。

         对两组数字分别进行 按位异或 运算,就可以得到要求的两个不同数。

        

         在求andr上为1的位时有个技巧   andr = andr &(-andr)

         -andr是通过对andr按位取反加1所得, andr & (-andr)就可以得到最低位的1所在位


源程序

输入输出 用scanf print,否则程序会超时

#include <iostream>
#include <stdio.h>
int nums[1000000];
int main()
{
      
	int n=0 ;
	int andr = 0;
	while(scanf("%d",&n) != EOF){
        int i = 0;
        andr = 0;
		while(i<n){
			scanf("%d",nums+i);
			andr^=nums[i];
			i++;
		}
		
		andr = andr &(-andr);
		i = 0;
		int num1=0;
		int num2=0;
		while(i<n){
			if(nums[i]&andr)
				num1^=nums[i];
			else
				num2^=nums[i];
			i++;
		}
		if(num1<num2)
			std::cout<<num1<<" "<<num2<<std::endl;
		else
			std::cout<<num2<<" "<<num1<<std::endl;
	}
	return 0;
}


你可能感兴趣的:(九度笔记之 1351:数组中只出现一次的数字)