• leetcode-260.只出现一次的数字 III


    位运算


    题目详情

    给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
    进阶:你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?


    示例1:

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

    示例2:

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

    示例3:

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

    方法一 哈希

    利用哈希map存储每个数字的次数,最后统计即可

    我的代码:

    class Solution 
    {
    public:
        vector<int> singleNumber(vector<int>& nums) 
        {
           unordered_map<int, int> map;
           for (int num : nums)
           {
               ++map[num];
           }
           vector<int> ans;
           for (const auto& [num, cishu]: map)
           {
               if (cishu == 1)
               {
                   ans.push_back(num);
               }
           }
           return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    方法二 简化问题 异或运算

    leetcode-136.只出现一次的数字 中,只有一个不同的数字,那么我们通过异或的方法最后留下来的就是答案,那么这道题如果我们仍然异或下来,那么最后留下的是两个答案的异或值(假设答案是a,b,最后留下的就是a ^ b),那么该咋办呢?哎呀!如果我们可以把a和b分开到两个数组里分别处理就好了
    我们可以知道,a ^ b就是将a和b的二进制每一位异或运算,当二者相同时就会得到0,否则就是1
    则我们可以像leetcode-136.只出现一次的数字 一样,先将所有数字异或运算,最后得到a ^ b
    然后找到这个结果的二进制中的某一个是1的位置,这个点就是分离a和b的关键
    我们找到这个位置之后,将原来的所有数中该位置是0的分为一组,该位置是1的分为一组
    我们再分别利用异或处理这两组,即可得到答案
    我们可以很方便的用x & -x 得到倒数第一位是1的数,但是要注意溢出问题
    因为若x = MIN_INT = -2147483648 则-x就是2147483648就会溢出(正数的最大值是2147483647)
    我们需要做些处理

    class Solution 
    {
    public:
        vector<int> singleNumber(vector<int>& nums) 
        {
           int allxorsum = 0;
           for (int num : nums) // 将所有数异或
           {
               allxorsum ^= num;
           }
           // 防止溢出
           int lsb = (allxorsum == INT_MIN ? allxorsum : allxorsum & (-allxorsum));
           int ty1 = 0, ty2 = 0;
           for (int num : nums)
           {
               if (num & lsb) // 对应位是1的归为一类进行异或运算
               ty1 ^= num;
               else           // 对应位是0的归为一类进行异或运算
               ty2 ^= num;
           }
           return {ty1, ty2};
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    位运算常用技巧

    位运算常用技巧

  • 相关阅读:
    victoriaMetrics无法获取抓取target的问题
    python去除列表中重复元素的方法
    MySQL Server 和 MySQL Workbench安装
    石子合并终极版 (GarsiaWachs算法) [o(n*n)] 板子
    U-Mail信创邮件系统解决方案
    Python安装第三方库的常用方法:使用pip
    jsp357校园点餐订餐系统ssm
    shell脚本之正则表达式
    26、类型别名
    如何使用Pyarmor保护你的Python脚本
  • 原文地址:https://blog.csdn.net/Gundam103/article/details/126179981