• 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?

    思路:位运算神题!

    这一题我们将所有的数都看作是二进制表示形式。

    因为所有的数都出现了三次,除了我们要求的数出现了一次。

    那么先考虑如果所有数都出现了三次是什么情况。

    将所有数都看作二进制表示形式,然后对于所有的数,我们计数二进制每一位上1出现的次数。

    因为所有数都出现了3次,因此每一位上的1也应该是3的倍数。

    现在,再添加一个只出现了一次的数。

    那么很容易发现,这个数所有二进制为1的位计数都加了1,于是这些位的计数就不再是3的倍数了!

    整理下思路就是,这些二进制位1的计数,每到3就归零,则综合最后为1的位就是这个数了。

    要计数二进制每一位1出现的次数,我们可以用数组,但是这里用两个int变量就够了。因为int本身就是一个32位变量,我们让其自身的每一位负责计数它对应那一位上1出现的次数。

    因为我们对于1的计数到3后就归零,因此两位二进制就可以表示:00、01、10、00。。。。

    然后我们将两个计数int变量命名为ones和twos,分别存储这个二进制计数的最低位和高位。

    而他们的变化流程如下:

      twos  ones

      0    0

      0    1

      1    0

      0    0

    先看ones的规律:ones与nums[i]异或,二进制位初始为0,与1异或1次后为1,异或2次后为0,异或3次后为1。但是根据上表,第三次时ones仍要为0,注意观察twos在第一次和第三次时的值,可以发现ones = (ones ^ nums[i]) & ~twos就能满足这个条件。

    twos的规律类似, 为twos = (twos ^ nums[i]) & ~ones。这里,因为twos要在ones之后计算才能实现表中的效果。

    最后所有值都异或完成后,所有出现3次的位都变为0,不是3次的则为1次。ones就是所求的数,而twos等于0。

     1 class Solution {
     2 public:
     3     int singleNumber(vector<int>& nums) {
     4         int ones = 0, twos = 0;
     5         for (int num : nums)
     6         {
     7             ones = (ones ^ num) & ~twos;
     8             twos = (twos ^ num) & ~ones;
     9         }
    10         return ones;
    11     }
    12 };
  • 相关阅读:
    OPENWRT 支持git
    LUCI MVC框架
    luci范例
    Hive | Hive可以避免进行MapReduce
    ORACLE日常-oracle中给date型字段insert into值
    ORACLE日常-ORACLE 中的 ROW_NUMBER() OVER() 分析函数的用法
    ORACLE日常-oracle字符串操作:拼接、替换、截取、查找
    HDFS中的shell操作
    java日常-map转成json
    java学习-reflection反射机制
  • 原文地址:https://www.cnblogs.com/fenshen371/p/4913826.html
Copyright © 2020-2023  润新知