leetcode260.只出现一次的数字III

题目链接

260. 只出现一次的数字 III - 力扣(LeetCode)

题目理解

不难理解,比如**[1,2,1,3,2,5]**中,3和5只出现过一次,因此输出3和5。主要难点在解题思路,这里不过多解释。

解题思路

这道题和平时见到的只出现一次的数字不同。因为这次我们有两个数字之出现了一次。因此我们不能将数字转换成二进制后取模。下面我们看一下这道题怎么解:

step1.全部异或

cpp 复制代码
1 ^ 2 ^ 1 ^ 3 ^ 2 ^ 5
= (1^1) ^ (2^2) ^ (3^5)  // 成对的互相抵消了!
= 0 ^ 0 ^ (3^5)
= 3 ^ 5
= 6

这里的6是3和5异或的结果。

把 3 和 5 写成二进制:

  • 3 → 011

  • 5 → 101

它们异或得到 6 → 110

关键观察 :6 的二进制 110 中,第二位的 1 表示 3 和 5 在这个位置不同!(其实第三位的1也表示3和5在那一位上不同,但我们通常取最低位的1)

  • 3 的第二位是 1

  • 5 的第二位是 0

异或不会计算的同学去复习一下,这里不多赘述了。


step2.找异或结果最低位的1

mix & (-mix) 能获取一个数字二进制表示中最低位的 1

-x 操作的实际含义:

cpp 复制代码
int x = 6;  // 计算机中存储:0000 0110(补码)

// 当你写 -x 时,计算机做的事情:
int y = -x;  // 计算过程:
              // 1. 取x的补码:0000 0110
              // 2. 按位取反:1111 1001
              // 3. 加1:1111 1010
              // 结果:这就是-6的补码表示!

**因此 mix & (-mix) 即为0000 0010,**这正是 6 的最低位的 1。


step3.分家法

用第二位作为"分家标准":

  • 第二位是 1 的站左边

  • 第二位是 0 的站右边

检查每个数字:

|----|-----|-----|-----|
| 数字 | 二进制 | 第二位 | 去哪边 |
| 1 | 001 | 0 | 右边 |
| 2 | 010 | 0 | 左边 |
| 1 | 001 | 0 | 右边 |
| 3 | 011 | 1 | 左边 |
| 2 | 010 | 1 | 左边 |
| 5 | 101 | 0 | 右边 |

结果:

  • 左边组:2, 2, 3

  • 右边组:1, 1, 5

分组后我们发现:

  • 3 和 5 被分到了不同的组!

  • 每组的其他数字都是成对的


step4. 各组异或

左边组 :2 ^ 2 ^ 3 = 3

  • 2 和 2 互相抵消

  • 剩下 3 ✓

右边组 :1 ^ 1 ^ 5 = 5

  • 1 和 1 互相抵消

  • 剩下 5 ✓

以下是该例子的可视化流程:

cpp 复制代码
原始数组:[1, 2, 1, 3, 2, 5]
            ↓
全部异或:6(3^5的混合体)
            ↓
找最低位1:2(二进制010)
            ↓
分组:
  左边(第二位=1):[2, 3, 2] → 异或得到 3
  右边(第二位=0):[1, 1, 5] → 异或得到 5
            ↓
答案:[3, 5]

总结一下 :先把所有数字异或得到"混合体",找到两个单身狗不同的一个二进制位,按这个位分组,然后每组分别异或,就得到了两个数字!

详解代码

cpp 复制代码
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        long long step1=0;
        //step1.全部异或
        for(auto it:nums)
        {
            step1^=it;
        }
        //step2 找异或结果最低位的1
        long long step2=step1&(-step1);
        //step3 分家法
        int result1=0,result2=0;
        //step4 各组异或
        for(auto it:nums)
        {
            if((step2&it)!=0)
            {
                result1^=it;
            }
            else
            {
                result2^=it;
            }
        }
        return {result1,result2};
    }
};

学会了就给博主点个赞呗?(✪ω✪)

---------(如有问题,欢迎评论区提问)---------

相关推荐
yi0115 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
灯澜忆梦8 小时前
【面向对象编程C++】| 基础语法
java·c++·算法
小蒋观天下8 小时前
专项方案:大场景港口AI安防、多干扰环境下的算法调优与落地实操
人工智能·深度学习·算法·安全·机器学习·计算机视觉·ai大模型
Evand J8 小时前
【电机滤波例程5】渐消因子自适应扩展卡尔曼滤波(EKF),MATLAB。PMSM负载突变下的状态估计。附下载链接
算法·matlab
H.莓飛8 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
好想像大佬一样能够ak所有9 小时前
Leetcode35.搜索插入位置
数据结构·算法·leetcode
aqiu1111119 小时前
【C++算法打怪专栏】LeetCode 165. 比较版本号(双指针与字符串流法)
c++·算法·leetcode
黄金龙PLUS9 小时前
如何基于置换算法来设计对称加密算法
算法·网络安全·密码学·哈希算法·同态加密
不会就选b9 小时前
算法日常・每日刷题--<动态规划>14
算法
赛博守夜人10 小时前
跨境业务与出海合规之九:海外买量投放与营销虚假流量(Ad Fraud):跨国机房群控与归因欺诈识别算法
算法·安全