LeetCode - Single Number II分析

原题如下:

"Given an array of integers, every element appears three times except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?"

Best answer 如下:

int singleNumber(int A[], int n) {
    int ones = 0, twos = 0, threes = 0;
    for (int i = 0; i < n; i++) {
        twos |= ones & A[i];//L1, 来0不变(安全)
        ones ^= A[i];//L2,  来1取反,来0不变(安全)
        threes = ones & twos;//L3, 后两位全1时为1,否则为0,。 确定threes位
        ones &= ~threes;//L4, threes是1时归零,否则不变。  确定ones位
        twos &= ~threes;//L5, threes是1时归零,否则不变。  确定twos位
    }
    return ones;
}

我们用L1~L5来标记关键代码以便叙述。

分析如下:

三个变量的意义摘录原文:

  1. ones as a bitmask to represent the ith bit had appeared once.
  2. twos as a bitmask to represent the ith bit had appeared twice.
  3. threes as a bitmask to represent the ith bit had appeared three times.
所以每当该位一个1到来时,(three,two,one)的变化规律为(0,0,0)*->(0,0,1)->(0,1,0)->(1,0,0)*->(0,0,1)->(0,1,0)->(1,0,0)->...,星号表示来1的个数为3的倍数,可以理解成循环边界,且只有第一次会出现000,以后边界都是100。

每当一个0到来时,该位不变,暂且称之为安全性。L1,L2行体现了两种安全操作,即“|= & ”和异或


现在在安全性基础上分析当1到来时的变化规律,观察三个位变化规律,如下图:


我们取一个周期,有a,b, c,d四行,d回到了a;threes, twos, ones三列。表面是简单的循环移位,其实不简单。

对于上述提到的安全操作异或,来1时置反。通过仔细观察,可以给ones用,得到ones位的规律是"0 1 0 1变化,当threes为1时归零。"分别由L2,L4实现。

对于另一个安全操作“|= &”,自然想到给twos用。观察L1得twos位的规律是“来0时不变(安全性);来1时,ones位为0则不变,为1则置1”。由L1实现。通过求索,可确定L1,L2的先后规律。。当然,和ones一样,还要补上L5的“当threes为1时归零”。

threes的规律比较简单,当后两位在执行完L1,L2后全1时置1,否则为0,如L3所示。

L4,L5只在three位为1时起作用,如图中d行红框所示。b,c行无中间过渡值。


总结

学到了两个“安全操作”:异或 和 "|= & "。

one, two ,three的变化规律相互依赖,其中one和异或是突破口。

本文旨在对这段代码的理解分析,至于大神是怎么想出这个算法的,只能自己体会了。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值