136、137、260  只出现一次的数字

    xiaoxiao2022-06-25  233

    一、136  数组中其他数都出现了2次,只有一个数出现了一次,把这个数找出来                           点击此处返回总目录

    二、137  数组中其他数都出现了3次,只有一个数出现了一次,把这个数找出来

    三、260  数组中其他数都出现了2次,只有两个数各出现了一次,把这两个数找出来

     

     

     

    一、数组中其他数都出现了两次,只有一个数出现了一次,把这个数找出来

     

    【题目】

     

    【分析】

    异或运算。不同为1,相同为0。所以2个相同的数异或得到一串0。

    0与1异或得1,0与0异或得0。所以0与一个数异或得到这个数本身。

    因此:把所有的数异或得到的就是这个数。

     

    【代码】

     

    【运行结果】

     

     

    二、数组中其他数都出现了三次,只有一个数出现了一次,把这个数找出来

     

    【题目】

     

    【分析】

    位运算。

    我们知道当数字x出现一次时,通过 x^0 可以记录下这个数x。

    当数字出现两次时,再通过x^x,就可以把这个数擦掉。

    因此,设置int a =[0][0][0][0][0][0][0][0],每个[0]代表一位。当x[i]出现偶数次时,a[i]^x[i] = 0。当x[i]出现奇数次时,a[i]^x[i]=x[i]。

     

     

    现在我们希望当数字出现一次时,记下来。当数字出现2次时,记下来。当数字出现3次时,置0。

    我们使用两个变量a和b做记录。

    int b=[0][0][0][0][0][0][0][0];

    int a=[0][0][0][0][0][0][0][0];

     

    我们需要:

    当x[i]出现1次时,b[i]=[0],a[i]=x[i]

    当x[i]出现2次时,b[i]=x[i],a[i]=0

    当x[i]出现3次时,b[i]=0,a[i]=0

     

           0     1     2     3     4      5     6

    b[i]: 0 -> 0 -> 1 -> 0  ->0 -> 1 -> 0

    a[i]: 0 -> 1 -> 0 -> 0 -> 1 -> 0 -> 0

     

    我们来看一下设计的逻辑:

    a = (a^ num) & ~b

    b = (b^ num) & ~a

     

    至于为什么这么设计,估计要回去复习一下逻辑电路那本书了。我们手动模拟一遍。

    初始: b[i]=0 a[i]=0

    当第一次出现1: a^1 = 1 , ~b = 1,1&1 = 1,所以a[i] = 1。b^1 = 1,~a = 0 , 1&0 = 0 ,所以b[i]=0。 正确。

    当第二次出现1: a^1 = 1^1 = 0 , ~b = 1,0&1 = 0,所以a[i]= 0。b^1 = 1,~a=1,1&1 = 1,所以b[i]=1。正确。

    当第三次出现1: a^1 = 0^1 = 1,~b = 0, 1&0 = 0,所以a[i] = 0。b^1 = 0,~a = 1, 0&1 = 0,所以b[i]=0。正确。

     

    初始:b[i]=0 a[i]=0

    当第一次出现0: a^0 = 0 , ~b = 1,0&1 = 0,所以a[i] = 0。b^0 = 0,~a = 1 , 0&1 = 0 ,所以b[i]=0。

    当第二次出现0: a^0 = 0^0 = 0,~b = 1,0&1 = 0,所以a[i] = 0。b^0 = 0,~a = 1,0&1 = 0,所以b[i]=0。

    当第三次出现0: a^0 = 0^0 = 0,~b = 1,0&1 = 0,所以a[i] = 0。b^0 = 0,~a = 1,0&1 = 0,所以b[i]=0。

    当出现0时,不改变a[i],b[i]的值。

     

     

    【代码】

     

    【结果】

     

     

     

    三、数组中其他数都出现了2次,只有两个数各出现了一次,把这两个数找出来

    【题目】

     

    【分析】

    比如有以下数字:

    2: 0 0 0 0 0 0 1 0 

    4: 0 0 0 0 0 1 0 0

    3: 0 0 0 0 0 0 1 1

    3: 0 0 0 0 0 0 1 1

    6: 0 0 0 0 0 1 1 0

    6: 0 0 0 0 0 1 1 0

     

    首先全部异或得到一个数,该数就是3和4异或的结果。

    a: 0 0 0 0 0 1 1 0

    分析这个数会发现,a中为0的位,说明原来的两个数这一位相同。a中为1的位,说明两个数这一位不同。

    这样我们就可以根据这一位将所有的数分成两堆,每一堆的结构如下:其他数都出现了两次,只有一个数出现了一次,找出这个数。这就变成了第一题。

    比如,根据倒数第2位将数划分为:

    (2,3,3,6,6)(4)

    根据倒数第3位将数划分为:

    (2,3,3)(4,6,6)

     

     

     

    【代码】

     

     

     

    【结果】

     

    红线划掉是因为,这是其他题目的提交记录。LeetCode不知道是不是有bug。

     

     

     

     

     

     

     

     

     


    最新回复(0)