leetcode_137.Single Number II

第一次写博客,有点小激动!
写这道题,主要是自己太菜,怕自己忘了。。。

原题

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,3,2]
输出: 3
示例 2:
输入: [0,1,0,1,0,1,99]
输出: 99

大佬的解题思路:
如果能设计一个状态转换电路,使得一个数出现3次时能自动抵消为0,最后剩下的就是只出现1次的数。

这里我找了一种较易理解的代码

public int singleNumber(int[] nums) {
        int one = 0, two = 0, three;
        for (int num : nums) {
            // two的相应的位等于1,表示该位出现2次
            two |= (one & num);
            // one的相应的位等于1,表示该位出现1次
            one ^= num;
            // three的相应的位等于1,表示该位出现3次
            three = (one & two);
            // 如果相应的位出现3次,则该位重置为0
            two &= ~three;
            one &= ~three;
        }
        return one;
    }

分析

1.这里的one、two、three的意思应该是:假如是(1,1,1)
当进入第一1的时候,one就为1,表示出现了一次
再进入一个1的时候,two也为1了,表示出现了两次
进入第三个1的时候,one、two都为1了,把three置为1表示出现了三次,这时候用~three做与运算,就是清零
这里把one、two、three都作为一种状态看

2.再看一下one、two、three本身
从二进制上用理解就000很容易了,还是以上面的例子看
当进入第一个1的时候,one=0001
进入第二个1的时候,one=0000,two=0001
进入第三个1的时候,one=two=0001,这时候three=0001,再~three和one、two做与运算,就置零了
(当然,这里的位数并不只是四位,与位数并不相关)

然后仔细一想,就发现,其实这个算法是在对每一个位进行运算,意思就是说每次进入一个数字的时候,
它二进制为1的部分就会放到one里面,如果one里面对应位置已经为1,则在two里面该位置1,表明该位
的1出现了两次,若one、two里面该位的值都为1,则three里面该位置1,然后就把该位置的1全部置零。
所以上面这种做法其实是对二进制上的每一位都进行了一种运算,只要该位出现过三次1,就会置0。所以无论
读入的数据怎样都无所谓,反正只要二进制上对应位的1出现过三次就置零。最后one里剩下就是只出现过
一次的数字的二进制信息。

理解:这里的实质应该是位运算,统计的是位上面的数字出现次数。可以联想,要是出现统计其他次数的,其实
也可以用这种对位运算的思想,而上面的代码具体实现就成了一种手段。

只能理解到这一步了,还得感谢一个朋友的帮忙。继续加油!!!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值