一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字,要求:时间复杂度为O(n),空间复杂度O(1)
输入:
8
{2,4,3,6,3,2,5,5}
输出:
4,6
使用异或解决问题:一个数异或自己等于0,异或其他数 != 0,如果是一个数字,那么一趟遍历数组异或之后的结果就是我们要的;而现在是2个数据,那么我们需要仔细考虑怎样将两个数字分开:
首先:将所有的数进行异或,得到一个结果不等于0的数字,因此这个结果数字在二进制位上必定最少有一位为1(因为那2个数不一样),我们从该结果的右边开始选择一个为1的位,记为第n位(这一位为1,那么就意味着第一个数的此位置上为1 ,第二个数此位置上肯定为0,或者反之,不然不可能异或 != 0);那么根据这一位的特性,将数组元素分成两个子数组,第一个子数组的每个数字的第n位为1,而第二个子数组中每个数字的第n位都是0;由于我们分组的标准是数字中的某一位是0还是1,那么出现了两次的数字肯定被分到了同一个数组;然后分别对这两部分进行再次异或得到两个数;
//查找整数number最右边是1的位
int findFistBitIs1(int number)
{
int index = 0;
while (((index & 1) == 0) && index <= sizeof(int) * 8)
{
number >>= 1;
++ index;
}
return index;
}
//测试number的从右边数第indexBit位是否为1
int isBit1OnIndex(int number, int indexBit)
{
int testNumber = 1 << indexBit;
return (number & testNumber);
}
int main()
{
freopen("input.txt","r",stdin);
int n;
cin >> n;
int *array = new int[n];
for (int i = 0; i < n; ++i)
{
cin >> array[i];
}
int testNumber = 0;
for (int i = 0; i < n; ++i)
{
testNumber ^= array[i];
}
int indexOf1 = findFistBitIs1(testNumber);
int ans1,ans2;
ans1 = ans2 = 0;
for (int i = 0; i < n; ++i)
{
if (isBit1OnIndex(array[i],indexOf1))
{
ans1 ^= array[i];
}
else
{
ans2 ^= array[i];
}
}
cout << ans1 << " " << ans2 << endl;
delete []array;
}原文地址:http://blog.csdn.net/zjf280441589/article/details/41621501