阅读目录
- 题目描述
- 思路与Python实现
- 思路一
- 思路二
题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
思路与Python实现
思路一
位运算 解法
- 我们知道,两个相同的数 按位异或 会等于0,并且 异或 满足交换律,如下图:
- 那么我们可以先依次对这个数组的每一个数,进行异或操作;那么结果就是:两个出现次数为1的数字的异或结果,而且它们的结果肯定不为0,也就是说在这个结果数字的二进制表示中至少就有一位为“1”,(如下图)接着就要用到这个特性!
- 在结果数字中找到第一个为“1”的位的位置,记为第N位;然后让这个以1位最高位的二进制数依次和数组每一位数进行按位与操作;结果:以第N 位是不是1 为标准把原数组中的数字分成两个子数组,因为第N为异或结果为1的话,这两个数的第N为一定是一个为0一个为1,那么我们就以这个标准对原数组的数划分为两个子数组,第一个子数组中每个数字的第N 位都为1 ,而第二个子数组的每个数字的第N 位都为0 。那么在这两个子数组中依次异或,得到的两个结果就是出现次数为1的数字。
class Solution:
def FindNumsAppearOnce(self, array):
if len(array) < 2:
return None
two_num_xor = None
for num in array:
if two_num_xor is None:
two_num_xor = num
else:
two_num_xor = two_num_xor ^ num
# 找出能将两个不同的数所在的领域分区的mask
count = 0
while two_num_xor % 2 == 0: # two_num_xor & 1 == 0 也行
two_num_xor = two_num_xor >> 1 # two_num_xor>>=1
count += 1
mask = 1 << count
# 然后在分别对两块区域进行按位异或操作,就能找出这两个不同的数
first_num = None
second_num = None
for num in array:
if mask & num == 0:
if first_num is None:
first_num = num
else:
first_num = first_num ^ num
else:
if second_num is None:
second_num = num
else:
second_num = second_num ^ num
return first_num, second_num
# 判断简写 因为任何数^0 都是本身
class Solution:
def FindNumsAppearOnce(self, array):
if len(array) < 2:
return None
two_num_xor = 0
for num in array:
two_num_xor = two_num_xor ^ num
count = 0
while two_num_xor & 1 == 0:
two_num_xor >>= 1
count += 1
mask = 1 << count
first_num = 0
second_num = 0
for num in array:
if mask & num == 0:
first_num = first_num ^ num
else:
second_num = second_num ^ num
return first_num, second_num
思路二
哈希表 字典 做法
- 利用字典,记录每个数字出现的次数,返回出现次数为1的数字,但是浪费空间
class Solution:
def FindNumsAppearOnce(self, array):
count = dict()
# count = {}
for i in array:
if i not in count:
count[i] = 0
count[i] += 1
result = []
for key,val in count.items():
if val == 1:
result.append(key)
else:
continue
return result
obj = Solution()
print(obj.FindNumsAppearOnce([1, 2, 1, 2, 3, 4, 5, 5, 4, 7]))