Open azl397985856 opened 2 years ago
位运算。
这个题是LeetCode136的加强版,136题中一趟异或即可搞定,这题弄一趟异或是不行的了,我们需要考虑分组处理,弄成2组,每一组满足LeetCode136的条件。
算法步骤: 对nums数组中的所有数异或运算, 算出两个落单数的异或结果theXor。
对theXor, 从低位开始向高位扫描, 找出两数的异或结果中的第1个1, 这恰好是两个落单数第一个不同的bit位。
接下来, 想办法把所有数分为2组, 且每个组只有1个落单的数, 只需要找一个概率均为50%的条件即可, 比如判断与mask最高位的同一个位置的二进制位是1还是0。
剩下的操作就是和LeetCode136 的位运算解法一样了。
实现语言: C++
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int theXor = 0;
for (int num : nums) // 对nums数组中的所有数异或运算, 算出两个落单数的异或结果
theXor ^= num;
int mask = 1;
while ((theXor & mask) == 0) /* 从低位开始向高位扫描, 找出两数的异或结果中的第1个1, 这恰好是两个落单数第一个不同的bit位 */
mask <<= 1;
/* 接下来, 想办法把所有数分为2组, 且每个组只有1个落单的数, 只需要找一个概率均为50%的条件即可, 比如判断数组中的每一个元素与mask最高位的同一个位置的二进制位是1还是0 */
int group1 = 0, group2 = 0;
vector<int> res;
for (int num : nums)
{
if (num & mask)
group1 ^= num;
else group2 ^= num;
}
res = {group1, group2};
return res;
}
};
Bitmask. Use XOR for all elements to get the XOR result (BITMASK) of two single elements. The variable BITMASK records the different bits of two single elements. Use BITMASK & (-BITMASK) to get the most right different bit (R_D) of two single elements. Use variable R_D to do the XOR again for all elements to get one single element X. The the other single element will be BITMASK^X
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
mask = 0
for i in nums:
mask ^= i
d = mask & (-mask)
x = 0
for i in nums:
if i & d:
x ^= i
return [x, mask ^ x]
Time: O(N) Space: O(1)
Explanation
Python
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
a = 0
for i in nums:
a ^= i
diff = a & (-a)
b = 0
for j in nums:
if j & diff:
b ^= j
return [b, a^b]
Complexity:
O(n)
O(1)
class Solution:
def singleNumber(self, nums):
s = reduce(xor, nums)
nz = s & (s-1) ^ s
num1 = reduce(xor, filter(lambda n: n & nz, nums))
return(num1, s ^ num1)
https://leetcode.com/problems/single-number-iii/
const singleNumber = function (nums) {
let set = new Set();
nums.forEach((x) => (set.has(x) ? set.delete(x) : set.add(x)));
return Array.from(set);
};
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
zor = reduce(xor, nums)
res = reduce(xor, filter(lambda i: i & (zor ^ (zor & (zor - 1))), nums))
return [res,res^zor]
public int[] singleNumber(int[] nums) {
int eor = 0;
for (int n : nums) {
eor ^= n;
}
int rightOne = eor & (~eor + 1);
int eor_ = 0;
for (int n : nums) {
if ((n & rightOne) == 0) {
eor_ ^= n;
}
}
int a = eor_;
int b = eor ^ a;
return new int[]{a,b};
}
Complexity: O(n); O(1)
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
x = reduce(xor, nums)
a = reduce(xor, filter(lambda n: n & (x&(-x)), nums))
return [a, x^a]
所有数字求异或,得到的结果是两个单独数字a和b的异或xor; 从右向左找到xor第一个二进制位取1的位置,根据异或性质,a和b在这个位置的二进制位不同 把数组分为两组,第一组在这个二进制位取0,另一组取1。 然后两组分别求异或,结果就是这两个数字。
class Solution {
public int[] singleNumber(int[] nums) {
int xor = 0;
for (int num: nums) {
xor ^= num;
}
int mask = 1;
while ((xor & mask) == 0) {
mask = mask << 1;
}
int[] ans = new int[2];
for (int num: nums) {
if ((num & mask) == 0) {
ans[0] ^= num;
} else {
ans[1] ^= num;
}
}
return ans;
}
}
TC: O(n) SC: O(1)
class Solution {
public int[] singleNumber(int[] nums) {
int sum = 0;
for (int i : nums){
sum ^= i;
}
int mask = 1;
while ((mask & sum) == 0){
mask <<= 1;
}
int[] res = new int[2];
for (int i : nums){
if ((mask & i) == 0){
res[0] ^= i;
} else {
res[1] ^= i;
}
}
return res;
}
}
https://leetcode.com/problems/single-number-iii/
class Solution {
public int[] singleNumber(int[] nums) {
int xor = 0;
for(int num: nums){
xor = xor ^ num;
}
int lowest = xor & (-xor);
int res1 = 0;
int res2 = 0;
for(int num: nums){
if((num & lowest) != 0){
res1 = res1 ^ num;
}else{
res2 = res2 ^ num;
}
}
return new int[]{res1, res2};
}
}
class Solution:
def singleNumber(self, A: List[int]) -> List[int]:
s = 0
for x in A:
s ^= x
y = s & (-s)
ans = [0,0]
for x in A:
if (x & y) != 0:
ans[0] ^= x
else:
ans[1] ^= x
return ans
C++ Code:
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
// 1. xor(a, a) = 0
//2. xor(a, 0) = xor(0, a) = a
//3. xor(1, 1) = xor(0, 0) = 0
//4. xor(1, 0) = xor(0, 1) = 1
///5. xor(a, b) = c => xor(a, c) = b and xor(b, c) = a
/// calculate c = a^ b
int bitTwoNum =0;
for(auto & it : nums)
bitTwoNum =(bitTwoNum ^ it) ;
/// find c right most
int rightMost = 1;
while( !(bitTwoNum & rightMost ) )
{
rightMost = rightMost << 1;
}
// get a or b.
int bitOneNum =0;
for(auto & it : nums)
{
if( it & rightMost)
{
bitOneNum =(bitOneNum ^ it);
}
}
// get another b or a
return {bitOneNum , bitOneNum ^ bitTwoNum} ;
}
};
先遍历一次 nums, 对于每个元素 n xorsum^= n
这样操作之后, 出现两次都数字都会被消去, 因为 i ^ i = 0, 最后 xorsum 只剩下出现一次的元素的xor, 即 xorsum = i ^ j, i, j 是 nums 中只出现了一次的元素
这个元素因为 i 和 j 只出现了一次并且不同, 所以 一定不为 0, 那么去出 这个 xorsum 的 最 least significant 1 (last_one = xorsum & -xorsum)
对于 last_one 这个元素, 因为 xor 之后是 1, 代表 只有两种情况, i & last_one = 1, j & last_one = 0 或者反过来 i & last_one = 0, j & last_one = 1
所以再次遍历数组, 用 last_one & n 将 i 和 j 区分开成为两组
分别两组做 nums1 ^= n, num2 ^= n, 之前出现两次都元素一定会被分进同一组, 于是会互相消去, i 和 j 一定会被分在两组, 于是剩下的 nums1 和 nums2 就是 i 和 j, 就是两个出现了一次的元素
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
xorsum = 0
for n in nums:
xorsum ^= n
last_one = xorsum & -xorsum
num1, num2 = 0, 0
for n in nums:
if last_one & n:
num1 ^= n
else:
num2 ^= n
return [num1, num2]
时间复杂度: O(n) 两次遍历的复杂度
空间复杂度: O(1)
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
s = set()
for num in nums:
if num in s: s.remove(num)
else: s.add(num)
return s
这才是承接136的题目,那个137根本就离谱的不着边
这个题目和136很相似,136是只出现一次的数字只有一个,通过异或的位运算可以巧妙的除掉所有其他数字,但此题出现的数字有两个,那当我们异或整个数组的时候,最终我们会得到两个不同的数异或的结果,而无法将其分开。
但是实际上这个结果是保留有特征的!举例来说,假设两个只出现一次的数是6和10,他们按位异或的结果是12。改写成二进制来看就是,b'00110'和b'01010'异或得到b'01100'。想想异或的原理能发现,结果中的1表示的是6和10的“不同”,即6和10的第3位一定是不同的。
有了这个结论,我们就可以利用这一点将数组分成两个部分,一部分的第三位位0,一部分的第三位为1。此时只出现一次的两个数字6和10一定会被分开,再分别对两个部分进行之前的异或操作即可。
这里补充一个快速找到异或结果中从右边开始第一个1的方法,即x&-x
。由于计算机语言中-x是x原码按位取反+1,两者相与的结果是从右往左的第一个1到末尾。举例而言,6是b'0110',-6是b'1010',他们与的结果是b'0010'。
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
ans = 0
for num in nums:
ans ^= num
mid = ans & -ans
ans_0, ans_1 = 0, 0
for num in nums:
if mid & num:
ans_0 ^= num
else:
ans_1 ^= num
return [ans_0, ans_1]
TC: O(n) SC: O(1)
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
total = 0
for n in nums:
total ^= n
mask = total & (-total)
res = [0, 0]
for n in nums:
if n & mask != 0:
res[0] ^= n
else:
res[1] ^= n
return res
class Solution {
public int[] singleNumber(int[] nums) {
int xorsum = 0;
for (int num : nums) {
xorsum ^= num;
}
int lsb = (xorsum == Integer.MIN_VALUE ? xorsum : xorsum & (-xorsum));
int type1 = 0, type2 = 0;
for (int num : nums) {
if ((num & lsb) != 0) {
type1 ^= num;
} else {
type2 ^= num;
}
}
return new int[]{type1, type2};
}
}
时间复杂度: O(n)
空间复杂度: O(1)
思路: 由于一个数组只有两个出现一次的数,其余都是出现两次的数。 我们对整个数组遍历求异或,可以得到两个出现一次的数想异或的结果。 此时利用 x&-x 可以得到这个数最低有效位,可以判断其中一个数与这位相与为0,另外一位数与这位相与为1. 因此用num1,num2分别记录。如果异或等于1则与num1异或,否则与num2异或。 最终回到只出现一次的数组1
func singleNumber(nums []int) []int {
num := 0
for i:=0;i<len(nums);i++{
num ^= nums[i]
}
lsb := num&-num
type1,type2 := 0,0
for i:=0;i<len(nums);i++{
if nums[i]&lsb > 0{
type1 ^= nums[i]
}else{
type2 ^= nums[i]
}
}
return []int{type1,type2}
}
时间复杂度O(n) 空间复杂度O(1)
位运算
JavaScript Code
var singleNumber = function (nums) {
let bitmask = 0;
for (let n of nums) {
bitmask ^= n;
}
bitmask &= -bitmask;
const ret = [0, 0];
for (let n of nums) {
if ((n & bitmask) == 0) ret[0] ^= n;
else ret[1] ^= n;
}
return ret;
};
复杂度
位运算
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
x=0
for i in nums:
x=x^i
t=0
while x>>t&1==0:
t+=1
a=0
b=0
for i in nums:
if i>>t&1==1:
a=a^i
else:
b=b^i
return [a,b]
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
unordered_map<int, int> map;
vector<int> res;
for (auto x : nums) map[x] ++;
for (auto &[k, v]: map) {
if (v == 1) {
res.push_back(k);
}
}
return res;
}
};
var singleNumber = function(nums) {
let set = new Set()
for(let i of nums){
if(set.has(i)) {
set.delete(i)
}else{
set.add(i)
}
}
return [...set]
};
python
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
xor = 0
for i in nums:
xor ^= i
mask = 1
while (mask & xor) == 0:
mask <<= 1
res = [0] * 2
for i in nums:
if i & mask == 0:
res[0] ^= i
else:
res[1] ^= i
return res
位运算
class Solution {
public int[] singleNumber(int[] nums) {
if(nums.length == 2) return nums;
int x = 0;
for(int i : nums){
x ^= i;
}
int n = 0;
for(int i = 0 ; i < 31 ;i++){
if(((x >> i) & 1) == 1){
n = i;
break;
}
}
int[] ans = new int[2];
for(int i : nums){
if(((i >> n) & 1) == 1) ans[0] ^= i;
else ans[1] ^= i;
}
return ans;
}
}
时间复杂度:O(n) 空间复杂度:O(1)
var singleNumber = function(nums) {
// 异或(相同为0,不同为1)
// 会消除出现两次的数字,total =会保留只出现一次的两个数字(x 和 y)之间的差异
let total = 0;
for(const i of nums){
total ^= i;
}
let diff = total & (-total);
// 从total中分离x和y
let x = 0;
for (let num of nums) {
if ((num & diff) != 0) {
x ^= num;
}
}
// 找到了x,则y = total^x
return [x, total^x];
};
class Solution { public int[] singleNumber(int[] nums) { if(nums.length == 2) return nums; int x = 0; for(int i : nums){ x ^= i; } int n = 0; for(int i = 0 ; i < 31 ;i++){ if(((x >> i) & 1) == 1){ n = i; break; } } int[] ans = new int[2]; for(int i : nums){ if(((i >> n) & 1) == 1) ans[0] ^= i; else ans[1] ^= i; } return ans; } }
https://leetcode-cn.com/problems/single-number-iii/
思考::存入哈希表,再找value=1的,时间复杂度是1但是空间复杂度是key。位运算可巧妙降低空间复杂度:
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
xor = a = b = 0
length = len(nums)
for i in nums:
xor ^= i
right_bit = xor & (-xor)#取最低位为1的数
for i in nums:
if right_bit & i:
a ^= i
else:
b ^= i
return [a, b]
复杂度分析:
var singleNumber = function (nums) {
let bitmask = 0;
for (let n of nums) {
bitmask ^= n;
}
bitmask &= -bitmask;
const ret = [0, 0];
for (let n of nums) {
if ((n & bitmask) == 0) ret[0] ^= n;
else ret[1] ^= n;
}
return ret;
};
https://leetcode-cn.com/problems/single-number-iii/
bitManipulation
class Solution:
def singleNumbers(self, nums: List[int]) -> List[int]:
# 获得ans1 ^ ans2的结果
target = 0
for num in nums:
target ^= num
# 获取不同的最后一位 用于分组
groupDivider = target & (-target)
num1 = num2 = 0
for num in nums:
# 表示只有这个位置没有1 所以&出来的结果为0
if num & (groupDivider) == 0:
num1 ^= num
# 如果这个位置有1 那么&出来的结果就不为0 可以是很多种情况
else:
num2 ^= num
return [num1, num2]
位运算
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int t=0;
for(auto x:nums)
t^=x;
int a=1;
while(!(a&t)){
a<<=1;
}
int t1=0,t2=0;
for(auto x:nums){
if(x&a){
t1^=x;
}else{
t2^=x;
}
}
return {t1,t2};
}
};
复杂度分析
查找表
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
nums_dict = collections.defaultdict(int)
for num in nums:
nums_dict[num] += 1
result_list = []
for num in nums_dict:
if nums_dict[num] == 1:
result_list.append(num)
return result_list
时间复杂度: O(N)
空间复杂度: O(N)
位运算
class Solution {
public int[] singleNumber(int[] nums) {
int xorSum = 0;
for (int num : nums) xorSum ^= num;
// rightSetBit为xorSum右侧第一个1
// int rightSetBit = 1;
// while ((rightSetBit & xor) == 0) rightSetBit <<= 1;
int rightSetBit = xorSum & -xorSum;
int res = 0;
for (int num : nums) {
if ((num & rightSetBit) != 0) res ^= num;
}
return new int[]{res, xorSum ^ res};
}
}
var singleNumber = function (nums) {
let diff = 0;
for (const num of nums) diff ^= num;
diff &= -diff;
let ans1 = (ans2 = 0);
for (const num of nums) {
if ((num & diff) > 0) ans1 ^= num;
else ans2 ^= num;
}
return [ans1, ans2];
};
Bit operation XOR
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
xor = x = y = 0
for num in nums:
xor ^= num
right_most = 1
while(right_most & xor == 0):
right_most <<= 1
for num in nums:
if right_most & num:
x ^= num
else:
y ^= num
return [x,y]
Space: O(1) Time: O(n)
异或 分组 再异或
我就喜欢reduce 慢也reduce
def singleNumber(self, nums: List[int]) -> List[int]:
x=reduce(lambda x,y:x^y,nums)
low=x&-x
return reduce(lambda x,y:(x[0]^y,x[1])if y&low else(x[0],x[1]^y),nums,[0,0])
Go Code:
func singleNumber(nums []int) []int {
xSum := 0
for _, num := range nums {
xSum ^= num
}
bit := xSum & (-xSum)
x, y := 0, 0
for _, num := range nums {
if bit&num == 0 {
x ^= num
} else {
y ^= num
}
}
return []int{x, y}
}
复杂度分析
令 n 为数组长度。
先xor得到两个只出现1次的元素的异或,其他元素出现两次xor得到0, 然后因为这两个元素不一样,必定一个某一位是1,而另一个这一位是0,找到任意这一位, 然后再遍历,把数组分为这一位为0,和为1的两组分别异或就得到结果
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
xor = 0
for num in nums:
xor ^= num
results = [0, 0]
k = 0
while (xor >> k & 1) == 0:
k += 1
for num in nums:
if (num >> k & 1) == 1:
results[0] ^= num
else:
results[1] ^= num
return results
Time O(n)
Space O(1)
思路:哈希表
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
# tc: O(N)
d = collections.defaultdict(int)
for i in nums:
d[i] += 1
ans = []
for key,value in d.items():
if value==1:
ans.append(key)
return ans
位运算。运用到异或运算的性质: A ^ A = 0, 0 ^ A = A
。因为题目中说数组中只有两个只出现一次的数字,先进行全数组异或运算,算出这两个只出现一次的数字的异或结果。之后对数组进行分组希望将这两个数字分到不同的组里。因为1 ^ 0 = 1
,我们从低位开始往高位找异或运算结果中第一个出现1的数位,按照此数位进行分组,两个数字一定不在一组,其余数字在各组中一定成对出现,再次进行组内元素异或运算即可求得结果。
class Solution {
public int[] singleNumber(int[] nums) {
int[] res = new int[2];
int xor = 0;
// perform xor for all the nums, xor = unique1 ^ unique2
for (int num : nums) {
xor ^= num;
}
// find the first different digit between unique1 and unique2
// starting from least significant digit
int mask = 1;
while ((xor & mask) == 0) {
mask = mask << 1;
}
// divide the nums into two groups, one has 0 at the corresponding digit
// and one has 1 at the corresponding digit
// unique1 and unique2 must be in two different groups
for (int num : nums) {
if ((num & mask) == 0) {
res[0] ^= num;
}
else {
res[1] ^= num;
}
}
return res;
}
}
复杂度分析
首先异或所有数,利用结果最右边的1,将所有数分成两组,其中两个只出现了一次的数将刚好被分别分在这两组。分别对两组进行异或,即可得到结果
class Solution {
public int[] singleNumber(int[] nums) {
int xor = 0;
for (int num : nums) {
xor ^= num;
}
int bit = xor & (-xor);
int x = 0, y = 0;
for (int num : nums) {
if ((num & bit) == 0) {
x ^= num;
} else {
y ^= num;
}
}
return new int[] {x, y};
}
}
时间:O(N)
空间:O(1)
位运算
class Solution {
public int[] singleNumber(int[] nums) {
int xor = 0;
for (int i : nums)
xor ^= i;
int mask = 1;
while ((mask & xor) == 0)
mask <<= 1;
int[] res = new int[2];
for (int i : nums) {
if ((i & mask) == 0)
res[0] ^= i;
else
res[1] ^= i;
}
return res;
}
}
思路:位运算
class Solution {
public int[] singleNumber(int[] nums) {
//因为相同的数字异或为0,任何数字与0异或结果是其本身。
//所以遍历异或整个数组最后得到的结果就是两个只出现一次的数字异或的结果:即 z = x ^ y
int z = 0;
for(int i: nums){
z = z ^ i;
}
//我们根据异或的性质可以知道:z中至少有一位是1,否则x与y就是相等的。
//我们通过一个辅助变量m来保存z中最低为的1.(可能有多个位都为1,我们找到最低位的1即可)。
//举个例子:z = 10 ^ 2 = 1010 ^ 0010 = 1000,第四位为1.
//我们将m初始化为1,如果(z & m)的结果等于0说明z的最低为是0
//我们每次将m左移一位然后跟z做与操作,直到结果不为0.
//此时m应该等于1000,同z一样,第四位为1.
//int m =1;
//while((z & m) == 0){
// m = m << 1;
//}
//
//同时也可以用645中用到的z & -z求最右位的1
int m = z & -z;
//我们遍历数组,将每个数跟m进行与操作,结果为0的作为一组,结果不为0的作为一组
//例如对于数组:[1,2,10,4,1,4,3,3],我们把每个数字跟1000做与操作,可以分为下面两组:
//nums1存放结果为0的: [1, 2, 4, 1, 4, 3, 3]
//nums2存放结果不为0的: [10] (碰巧nums2中只有一个10,如果原数组中的数字再大一些就不会这样了)
//此时我们发现问题已经退化为数组中有一个数字只出现了一次
//分别对nums1和nums2遍历异或就能得到我们预期的x和y
int x = 0, y = 0;
for(int i: nums){
//这里我们是通过if...else将nums分为了两组,一边遍历一遍异或。
//跟我们创建俩数组nums1和nums2原理是一样的。
if((i & m) == 0){
x = x ^ i;
}else{
y = y ^ i;
}
}
return new int[]{x, y};
}
}
时间复杂度:O(N) 空间复杂度:O(1)
Use of XOR, then use a mask & xor to find the difference of those two numbers, use it to split this question into simple question: find one unique number
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
xor = a = b = 0
#step 1. xor all num in nums, eventually will get that two unique number's xor
for num in nums:
xor ^= num
#find a location where these two numbers are different at this bit
mask = 1
while mask & xor == 0:
mask <<= 1
#step 3. use this location to split it into subquestion: find one value that only appear once
for num in nums:
if mask & num == 0:
a ^= num
else:
b ^= num
return [a, b]
https://leetcode.com/problems/single-number-iii/submissions/
bitmask
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
# difference between two numbers (x and y) which were seen only once
bitmask = 0
for num in nums:
bitmask ^= num
# rightmost 1-bit diff between x and y
diff = bitmask & (-bitmask)
x = 0
for num in nums:
# bitmask which will contain only x
if num & diff:
x ^= num
return [x, bitmask^x]
# time complexity O(N) space complexity O(1)
DP 时间复杂度: O(N) 空间复杂度:O(1)
vector<int> singleNumber(vector<int>& nums)
{
int thexor = 0;
// 异或可以把重复的数消掉
for(auto i: nums)
thexor ^= i;
int mask = 1;
while((thexor & mask) == 0)
mask <<= 1;
int group1 = 0, group2 = 0;
for(auto i: nums)
{
// 将原数组分为两部分,一部分是与mask不等于0的为一组,等于0的为另一组
if(i & mask)
group1 ^= i;
else
group2 ^= i;
}
return vector<int>{group1, group2};
}
class Solution {
public int[] singleNumber(int[] nums) {
int eor = 0;
for (int n : nums) {
eor ^= n;
}
int rightOne = eor & (~eor + 1);
int eor_ = 0;
for (int n : nums) {
if ((n & rightOne) == 0) {
eor_ ^= n;
}
}
int a = eor_;
int b = eor ^ a;
return new int[]{a,b};
}
}
思路: 方法一、哈希表/数组 方法二、位运算,异或
复杂度分析:
代码(C++):
方法一、
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int n = nums.size();
unordered_map<int, int> memo;
for (int num : nums)
memo[num]++;
vector<int> res;
for (int num : nums) {
if (memo[num] == 1)
res.push_back(num);
}
return res;
}
};
方法二、
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int mask = 0;
for (int num : nums)
mask ^= num;
int idx = 1;
while ((mask & idx) == 0)
idx <<= 1;
vector<int> res(2, 0);
for (int num : nums) {
if ((idx & num) == 0)
res[0] ^= num;
else
res[1] ^= num;
}
return res;
}
};
class Solution {
public int[] singleNumber(int[] nums) {
if (nums.length == 2) {
return nums;
}
int xor = 0;
for (int num : nums) {
xor ^= num;
}
int divide = xor & (~xor + 1); // 分治
int num1 = 0;
int num2 = 0;
for (int num : nums) {
if ((num & divide) == 0) {
num1 ^= num;
} else {
num2 ^= num;
}
}
return new int[] { num1, num2 };
}
}
思路: bit manipulation, XOR all numbers in the input array, then we have (a XOR b), assuming a and b are the two numbers which are distinct and appear only once, then we can get the lowest bit for (a XOR b), which must not be zero, then we can partition the numbers in the input array into two groups, a and b fall into two groups, finally we can just XOR all numbers in each group to get the result
class Solution {
public int[] singleNumber(int[] nums) {
int aXORb = 0;
for (int num : nums) {
aXORb ^= num;
}
int lowestBit = aXORb & -aXORb;
int[] result = new int[2];
for (int num : nums) {
if ((num & lowestBit) == 0) {
result[0] ^= num;
} else {
result[1] ^= num;
}
}
return result;
}
}
Time Complexity: O(n) Space Complexity: O(1)
260. 只出现一次的数字 III
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/single-number-iii/
前置知识
题目描述
示例 :
输入: [1,2,1,3,2,5] 输出: [3,5] 注意:
结果输出的顺序并不重要,对于上面的例子, [5, 3] 也是正确答案。 你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?