今天碰到的题相对较难,即使看了题解依然花了较长时间才解出,在此记录,同时复习一下python的位运算。
该题的解题流程如下:
- 遍历一遍数组,然后对数组中每个值都进行异或操作,相同的两个元素异或后全部变成了0,因此实际上数组的每个值异或后就是两个不同的元素进行异或的结果。两个不同的值异或的结果有一个特殊的地方需要掌握,将这两个不同的值A,B都转化为二进制,比如1101,1111,他们异或后就变成了0010,也就是只有不同的位是1,其他都是0,当然异或后可能有多个位是1,因为可能转化为二进制后多个位都不同。
- 遍历求解出step 1结果中最低位的1所在的位置。step 1我们得到了A和B异或的结果,这一步step 2就是要知道结果的最低位的1是哪一位,比如0010,最低位的1就是第2位了,那么这一步就得到10,我们称之为C。
- 遍历数组array,将step 2得到的最低位1的结果C和array的元素num去做&运算,我们可以知道,数组中唯二两个不同的数一个和C做&肯定是0,一个不是0,因此这两个数就被C的&运算区分开来了,这样就可以把这两组分别去做异或,就分别得到了两个不同的数,返回即可。
代码如下
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param array int整型一维数组
# @return int整型一维数组
#
class Solution:
def FindNumsAppearOnce(self , array) :
# write code here
tmp = 0
for num in array:
tmp ^= num
# 找到最低位的1
group = 1
while group & tmp == 0:
group = group << 1
# 分组寻找两个只出现过一次的数
tmp1 = 0 ; tmp2 = 0
for num in array:
if num & group == 0:
tmp1^=num
else:
tmp2^=num
return sorted([tmp1,tmp2])
array = [1,4,1,6]
print(Solution().FindNumsAppearOnce(array))
关于位运算,在算法里做到的不多,因此往往想不到,而且位运算也差不多快忘了,在这边复习记录一下。
常见的位运算就是异或:同0异1;与:都是1才是1,否则0,或:有一个1就是1,全0为0。python里分别是^,&,|。
左移<<,也就是二进制左移y位,比如x<<y,也就是x左移y位,以2<<1举例说明,2进行二进制转换后是10,左移一位就是100,也就是
2
∗
2
1
=
4
2*2^1=4
2∗21=4,因此x<<y也就是
x
∗
2
y
x*2^y
x∗2y。右移就是把乘改成除而已,2>>1就是1,也就是
2
/
2
1
2/2^1
2/21。
最后看下python里二进制怎么转十进制,十进制怎么转回二进制。
十进制转二进制
print(bin(2))
print(bin(7))
print(type(bin(2)))
结果:
0b10
0b111
<class 'str'>
二进制转十进制
print(int("1000",2))
print(int('0b1000',2))
结果:
8
8