You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LeetCode 137题位运算解法逻辑深度解析

理解LeetCode 137题的位运算解法:只出现一次的数字II

先贴出你提到的核心代码:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ones = 0, twos = 0;
        for(int i=0; i < nums.size(); i++) {
            ones = (ones ^ nums[i]) & ~twos;
            twos = (twos ^ nums[i]) & ~ones;
        }
        return ones;
    }
};

这个解法的核心是用ones和twos两个变量,分别记录二进制每一位出现1次和2次的状态,每一位的状态变化遵循「00→01→10→00」的循环(对应该位被0次、1次、2次、3次覆盖)。你困惑的点在于计算顺序——代码中是先更新ones,再用更新后的ones计算twos,这是关键,下面用数字3(二进制11)的两次出现过程来拆解:

第一次遇到3:

初始状态:ones=0,twos=0

  1. 更新ones:(0 ^ 11) & ~0 = 11 & 全1 = 11 → 此时ones=11(对应该位出现1次)
  2. 更新twos:(0 ^ 11) & ~11 = 11 & 全0 = 0 → twos保持0

第二次遇到3:

注意,这里计算twos时用的是刚更新后的ones:

  1. 先更新ones:(11 ^ 11) & ~0 = 0 & 全1 = 0 → ones变为0(该位出现次数从1次清零,准备转移到twos)
  2. 再更新twos:(0 ^ 11) & ~0 = 11 & 全1 = 11 → twos变为11(该位出现次数变为2次)

你之前误以为计算twos时用的是更新前的ones(11),但实际上代码里ones已经先被更新成0了,所以~ones是全1,自然能把3加入twos桶。

状态转移表(单二进制位)

我们可以把每一位的状态单独拎出来看,更清晰:

当前(ones位, twos位)遇到1时新状态遇到0时新状态
(0, 0)(1, 0)(0, 0)
(1, 0)(0, 1)(1, 0)
(0, 1)(0, 0)(0, 1)

因为题目中除了目标元素,其他元素都出现3次,所以这些元素的每一位都会走完「00→01→10→00」的循环,最终回到00状态;而目标元素只出现1次,对应的位会停在「01」状态,也就是ones中对应的位为1,所以最终返回ones就是答案。

内容的提问来源于stack exchange,提问作者Gopika J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 02:52:16