天天看点

lintcode 落单的数(位操作)

  给出2*n + 1 个的数字,除其中一个数字之外其他每个数字均出现两次,找到这个数字。

  给出 [1,2,2,1,3,4,3],返回 4

  一次遍历,常数级的额外空间复杂度

  方法1思路:将所有的数转换成二进制,因为是int类型,共32位。申请常数级(32位)的额外空间,然后每个数对应的位相加,最后对应位上的和模2。最后的结果就是单个数对应的二进制数。

lintcode 落单的数(位操作)
lintcode 落单的数(位操作)

  方法2思路:通过异或,相同的数结果为0,那么最后的结果一定是落单的数字。

lintcode 落单的数(位操作)
lintcode 落单的数(位操作)

  给出3*n + 1 个的数字,除其中一个数字之外其他每个数字均出现三次,找到这个数字。

  给出 [1,1,2,3,3,3,2,2,4,1] ,返回 4

  同上一题的方法1一样的思路。

lintcode 落单的数(位操作)
lintcode 落单的数(位操作)

  给出2*n + 2个的数字,除其中两个数字之外其他每个数字均出现两次,找到这两个数字。

  给出 [1,2,2,3,4,4,5,3],返回 1和5

  o(n)时间复杂度,o(1)的额外空间复杂度

      

lintcode 落单的数(位操作)

  如上图所示,所有数的异或的结果等于两个落单数异或的结果(设为s)。如何根据这个异或的结果将落单的数找出来呢?首先,s的值一定不为0,那么找到s对应的二进制数值为1的位(找到任意一个位为1都行, 这里我们找到s的二进制最后一个为1的位,设为p),根据这一个位置,将所有的数划分成两部分,一部分是对应二进制p位是1,另一部分对应二进制p位是0。这样就把两个落单的数划分到了不同的集合里去了。如上图的红色框集合和绿色框集合。然后就转换成“2*m+1个数字,除了一个数字其他数字均出现两次”的问题,也就是题目1:落单的数i。

lintcode 落单的数(位操作)
lintcode 落单的数(位操作)

继续阅读