数组中只出现一次的数字,时间复杂度O(n),空间复杂度O(1)的解法
2015-06-04 10:46
323 查看
题目:一个整型数组里除了两个数组外,其他的数字都出现了两次,要找出这两个数字。
异或运算有一个性质:任何数异或它自己,结果都是0;这样如果题目变成只有一个数字只出现一次,其他数字均出现两次,这样我们从头到尾异或数组中的每一个数字,那么最终的结果就是只出现一次的数字。
如果可以把数组中的数字分成两个子数组,每个数组里面包含一个只出现一次的数字,其他的数字都出现两次,这样按照上面的方法就可以分别求出只出现一次的数字了。首先,我们从头到尾异或数组中的每一个数字,那么得到的结果将是这两个只出现了一次的数字异或后的结果(因为其他出现了两次的数字都在异或中抵消了)。由于这两个数字不相同,所以它们的异或结果的二进制表示中至少有一位是1.我们先找到第一个为1的位的位置,记为第n位。然后我们以第n位是否为1,把原数组分成两个子数组,第一个数组中每个数的第n位都为1,第二个数组中的每个数的第n位都为0,因为两个相同的数字的任意一位都是相同的,所以相同的数肯定分在同一组,这样我们就实现了划分子数组的效果。
参考代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
bool Is1(int n,unsigned int bit)
{
n=n>>bit;
return (n&1);
}
unsigned int FindFirstBit1(int n)
{
int bit=0;
while((n&1)==0&&bit<8*sizeof(int))
{
n=n>>1;
bit++;
}
return bit;
}
void FindNums(int data[],int len,int &num1,int &num2)
{
if(data==NULL||len<2)
return;
int ans=0;
for(int i=0;i<len;i++)
ans=ans^data[i];
unsigned int bit=FindFirstBit1(ans);
for(int i=0;i<len;i++)
{
if(Is1(data[i],bit))
num1=num1^data[i];
else
num2=num2^data[i];
}
}
int main()
{
int num1=0,num2=0;
int data[100];
int len;
scanf("%d",&len);
for(int i=0;i<len;i++)
scanf("%d",&data[i]);
FindNums(data,len,num1,num2);
printf("%d %d",num1,num2);
}
异或运算有一个性质:任何数异或它自己,结果都是0;这样如果题目变成只有一个数字只出现一次,其他数字均出现两次,这样我们从头到尾异或数组中的每一个数字,那么最终的结果就是只出现一次的数字。
如果可以把数组中的数字分成两个子数组,每个数组里面包含一个只出现一次的数字,其他的数字都出现两次,这样按照上面的方法就可以分别求出只出现一次的数字了。首先,我们从头到尾异或数组中的每一个数字,那么得到的结果将是这两个只出现了一次的数字异或后的结果(因为其他出现了两次的数字都在异或中抵消了)。由于这两个数字不相同,所以它们的异或结果的二进制表示中至少有一位是1.我们先找到第一个为1的位的位置,记为第n位。然后我们以第n位是否为1,把原数组分成两个子数组,第一个数组中每个数的第n位都为1,第二个数组中的每个数的第n位都为0,因为两个相同的数字的任意一位都是相同的,所以相同的数肯定分在同一组,这样我们就实现了划分子数组的效果。
参考代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
bool Is1(int n,unsigned int bit)
{
n=n>>bit;
return (n&1);
}
unsigned int FindFirstBit1(int n)
{
int bit=0;
while((n&1)==0&&bit<8*sizeof(int))
{
n=n>>1;
bit++;
}
return bit;
}
void FindNums(int data[],int len,int &num1,int &num2)
{
if(data==NULL||len<2)
return;
int ans=0;
for(int i=0;i<len;i++)
ans=ans^data[i];
unsigned int bit=FindFirstBit1(ans);
for(int i=0;i<len;i++)
{
if(Is1(data[i],bit))
num1=num1^data[i];
else
num2=num2^data[i];
}
}
int main()
{
int num1=0,num2=0;
int data[100];
int len;
scanf("%d",&len);
for(int i=0;i<len;i++)
scanf("%d",&data[i]);
FindNums(data,len,num1,num2);
printf("%d %d",num1,num2);
}
相关文章推荐
- maven安装
- SAP 让库龄表飞起来!
- 学习笔记:架构 移动应用架构 开篇(一)
- 评教,路上的风景更美
- Oracle 生成和显示执行计划的方法
- c:choose、c:when、c:otherwise 使用
- iOS已发布应用中对异常信息捕获和处理
- typeof关键字
- csu1651 Weirdo 最均匀路径
- Android再按一次返回键退出程序
- 类的静态成员
- AVC1与H264的差别
- 按需讲解之Supervisor
- PHP杂记
- centos下 安装jdk
- 修改属性页CPropertyPage标题
- 【VB.NET机房重构】ADO.NET
- Maximal Square
- C#中重写(override)和覆盖(new)的区别
- JavaScript中指定函数名称的相关方法