Leetcode.260 只出现一次的数字 III

题目链接

Leetcode.260 只出现一次的数字 III mid

题目描述

给你一个整数数组 n u m s nums nums,其中恰好有两个元素只出现一次其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。

示例 1:

输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。

示例 2:

输入:nums = [-1,0]
输出:[-1,0]

示例 3:

输入:nums = [0,1]
输出:[1,0]

提示:
  • 2 ≤ n u m s . l e n g t h ≤ 3 ∗ 1 0 4 2 \leq nums.length \leq 3 * 10^4 2nums.length3104
  • - 2 31 ≤ n u m s [ i ] ≤ 2 31 − 1 2^{31} \leq nums[i] \leq 2^{31} - 1 231nums[i]2311
  • 除两个只出现一次的整数外, n u m s nums nums 中的其他数字都出现两次

解法:位运算

由于 n u m s nums nums 中只有两个数 x x x y y y 分别出现一次,其他元素都出现了两次。

所以直接对整个 n u m s nums nums 进行 异或,最后的结果实际上就是 x x o r y x \quad xor \quad y xxory,因为相同的元素异或为0。

假设此时的 x = 3 = ( 0011 ) 2 , y = 5 = ( 0101 ) 2 x = 3 = (0011)_2 , y = 5 = (0101)_2 x=3=(0011)2,y=5=(0101)2 , 异或的结果为 t = 6 = ( 0110 ) 2 t = 6 = (0110)_2 t=6=(0110)2

假设 t t t 的第 k k k 二进制位为 1 1 1 得话,说明要么是 x x x k k k 个二进制位为 1 1 1;说明要么是 y y y k k k 个二进制位为 1 1 1。不可能同时为 1 1 1

所以通过这个 ,我们就可以将 x x x y y y 分开。因为直接将 x x x y y y 2 k − 1 2^{k - 1} 2k1 分别进行 与操作,结果分别为 2 k − 1 2^{k - 1} 2k1 0 0 0

另外,由于其他元素都是成对出现的,所以每一对元素对 2 k − 1 2^{k - 1} 2k1 进行 与操作,结果都是一样的,也就是他们会被分到同一组。

假设结果 t = ( 101011100010 ) 2 t = (101011100010)_2 t=(101011100010)2,使用任何一个 1 1 1 来进行上述的操作其实都可以的,想用哪个就用哪个。不过为了方便起见,直接使用最低位的那个 1 1 1 ,也就是 t = ( 101011100010 ) 2 t = (1010111000 \mathbf{1}0)_2 t=(101011100010)2

我们可以通过以下操作得到 t t t 最低位的 1 1 1

int k = t & (-t);

 t = 1010 1110 0010
 &
-t = 0101 0001 1110
     0000 0000 0001

时间复杂度: O ( n ) O(n) O(n)

C++代码:

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        unsigned int t = 0;
        for(auto x:nums) t ^= x;

        int k = t & ( -t);

        vector<int> ans(2);

        for(auto x:nums){
            if((x & k) == k) ans[0] ^= x;
            else ans[1] ^= x;
        }

        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值