问题1:问题是一堆数,只有一个数只出现1次,其余数都出现2次,怎么求出这个数?spa
咱们知道位运算里面的异或操做,当两个数相同时,获得的结果是零。因此咱们简单的把全部数一块儿求异或就获得了答案。code
更通常的,只有1个数出现奇数次,其余数都出现偶数次,均可以这么解决。blog
代码以下io
class Solution { public: int singleNumber(vector<int>& nums) { int ones = 0, i; for (i = 0; i < nums.size(); ++i) ones ^= nums[i]; return ones; } }
问题2:问题是一堆数,只有2个数只出现1次,其余数都出现2次,怎么求出这个数?class
基于上面的题,咱们知道了,只有1个数的状况下怎么求出这个数。若是对于本题,咱们用上面的方法,求出的结果是这两个只出现1次的数的异或。方法
咱们知道若是这两个数异或结果中某一位是1,说明这2个数在这一位是不一样的。所以咱们能够取出这一位,而后用这一位给数分桶,两桶中的数就分别变成了问题1。di
代码以下co
class Solution { public: vector<int> singleNumber(vector<int>& nums) { int ones = 0, left = 0, right = 0, i; for (i = 0; i < nums.size(); ++i) ones ^= nums[i]; ones &= -ones;//取出最低不为0的一位 for (i = 0; i < nums.size(); ++i) { if (ones & nums[i]) left ^= nums[i]; else right ^= nums[i]; } return {left, right}; } };
问题2:问题是一堆数,只有3个数只出现1次,其余数都出现2次,怎么求出这个数?位运算
基于上面的题,咱们又知道了,只有2个数的状况下怎么求出这2个数。若是对于本题,咱们只须要稍微改动上面的方法,就获得了答案。return
用上面的方法,分桶求出后,咱们获得两个数,其中一个是这三个数的某个数自己,另外一个是其余两个数的异或。
若是对两个桶再分桶一次,那么包含一个数的那个桶,获得了那个数自己和0, 另一个桶分桶就获得了剩下的两个数。
代码以下
class Solution { public: vector<int> singleNumber(vector<int>& nums) { int ones = 0, left = 0, right = 0, a = 0, b = 0, c = 0, d= 0, i; for (i = 0; i < nums.size(); ++i) ones ^= nums[i]; ones &= -ones;//取出最低不为0的一位 for (i = 0; i < nums.size(); ++i) { if (ones & nums[i]) left ^= nums[i]; else right ^= nums[i]; } left &= -left; right &= -right; for (i = 0; i < nums.size(); ++i) { if (ones & nums[i]) if (left & nums[i]) a ^= nums[i]; else b ^= nums[i]; else if (right & nums[i]) c ^= nums[i]; else d ^= nums[i]; } if (a == 0) return {b, c, d}; if (b == 0) return {a, c, d}; if (c == 0) return {a, b, d}; return {a, b, c}; } };