面试题44:数组中只出现1次的数字

题目:

一个整型数组中,除了两个数字之外,其他的数字都出现了两次。求写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

边界条件及异常:
数组为空,没有只出现一次的数,只有一个只出现一次的数。

思路:
这题好难!

首先我们考虑如果数组中只有一个数字只出现一次,其他的都出现两次,应该怎样做?

由于两个相同数字异或后为0,所以我们可以将数组从第一个数开始到最后一个数进行异或,最后得到的结果就是只出现一次的数字。

但是如果有两个只出现一次的数呢?
书中提供的思路是将数组分成两部分,每部分包含一个只出现一次的数字和其他只出现两次的数字。那么问题来了,怎么分呢?
我们先将所有数字异或,最后得到的结果是那两个只出现一次的数字的异或,由于这两个数字不相同,所以不为0。

我们在结果中找到第一个不为0的位置,记为第n位。

于是我们分组时可以根据第n位是0还是1来分,这样可以保证:

1)两个只出现一次的数在不同的组

2)相同的数字在同一个组

分组完成后就按照只有一个数字出现一次来做就OK了。

#include <iostream>      
#include <vector>   
#include <queue>  
#include <string>      
#include <stack>      
#include <algorithm>    
#include <hash_set>  //for hashtable  
#include <hash_map>  
#include <unordered_map>  
#include <set>  
#include <ctime>  
using namespace std;

using namespace std;

bool IsBit1(int num, unsigned int indexBit)
{
	num = num >> indexBit;
	return (num & 1);
}

unsigned int FindFirstBitIs1(int num)
{
	int indexBit = 0;
	while ((num & 1) == 0 && (indexBit < 8 * sizeof(int)))
	{
		num = num >> 1;
		++indexBit;
	}
	return indexBit;
}

void FindNumsAppearOnce(vector<int> nums, int &num1, int &num2)
{
	int size = nums.size();
	if (size < 2) return;
	int reExclusiveOr = 0;
	for (int i = 0; i < size; ++i) reExclusiveOr ^= nums[i];
	int indexOf1 = FindFirstBitIs1(reExclusiveOr);
	num1 = 0, num2 = 0;
	for (int j = 0; j < size; ++j)
	{
		if (IsBit1(nums[j], indexOf1)) num1 ^= nums[j];
		else num2 ^= nums[j];
	}
}


int main()
{
	int arr[] = { 1, 2, 3, 4, 3, 2 };
	vector<int>nums(arr, arr + 6);
	int num1 = 0, num2 = 0;
	FindNumsAppearOnce(nums, num1, num2);
	cout << num1 << " " << num2 << endl;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值