力扣面试题56 - I. 数组中数字出现的次数(异或、位运算)
https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
算法
先对所有数字进行一次异或,得到两个出现一次的数字的异或值。
在异或结果中找到任意为 1的位。
根据这一位对所有的数字进行分组。
在每个组内进行异或操作,得到两个数字。
扫描二维码关注公众号,回复:
11944668 查看本文章
复杂度分析
-
时间复杂度:O(n),我们只需要遍历数组两次。
-
空间复杂度:O(1),只需要常数的空间存放若干变量。
位运算(&、|、^、~、>>、<<) - 五色风车 - 博客园
https://www.cnblogs.com/yrjns/p/11246163.html
#include "stdafx.h"
#include <vector>
#include <iostream>
using namespace std;
class Solution
{
public:
vector<int> singleNumbers(vector<int>& nums)
{
int a = 0;
int b = 0;
int temp = 0;
int bit = 1;
//先对所有数字进行一次异或,得到两个出现一次的数字的异或值
for (int i = 0; i < nums.size(); i++)
{
temp = temp^nums[i];
}
//在异或结果中找到任意为 1 的位。
//这里注意要带括号,因为==的优先级大于&。
while ((temp&bit) == 0)
{
bit = bit << 1;
}
for (int i = 0; i < nums.size(); i++)
{
cout << nums[i] << '\n';
//根据这一位对所有的数字进行分组。
//在每个组内进行异或操作,得到两个数字。
if ((nums[i] & bit) == 0)
{
a = a^nums[i];
}
else
{
b = b^nums[i];
}
}
cout << a << '\t' << b;
vector<int>result;
result.push_back(a);
result.push_back(b);
return result;
}
};
int main()
{
Solution s;
vector<int> nums;
nums.push_back(1); nums.push_back(2); nums.push_back(10);
nums.push_back(4); nums.push_back(1); nums.push_back(4);
nums.push_back(3); nums.push_back(3);
auto result = s.singleNumbers(nums);
return 0;
}