题目描述:
数组中有 N+2 个数,其中,N 个数出现了偶数次(即这N个数出现的次数都是偶数),2个数出现了奇数次(这两个数不相等),请用O(1)的空间复杂度,找出这两个数。注意:不需要知道具体位置,只需要找出这两个数。
方法:
- 字典法
- 异或法
1.字典法
定义一个字典,把数组元素的值作为 key,遍历整个数组,如果 key 值不存在,则将value设为1,如果 key 值已经存在,则翻转该值(如果为0,则翻转为1;如果为1,则翻转为0).在完成数组遍历后,字典中 value 为1的就是出现奇数次的数。
代码实现:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2020/1/27 19:03
# @Author : buu
# @Software: PyCharm
# @Blog :https://blog.csdn.net/weixin_44321080
def get2Num(arr):
if arr == None or len(arr) < 1:
print('参数不合理!')
return
dic = dict()
i = 0
while i < len(arr):
if arr[i] not in dic.keys():
dic[arr[i]] = 1
else:
dic[arr[i]] = 0
i += 1
for k, v in dic.items():
if v == 1:
print(k, end=' ')
if __name__ == '__main__':
arr = [3, 5, 6, 6, 5, 7, 2, 2]
print('result:', end='')
get2Num(arr)
结果:
算法性能分析:
此方法对数组进行了一次遍历,时间复杂度为O(n);
但是申请了额外的存储空间来记录数据出现的情况,空间复杂度为O(n);
2.异或法
根据异或运算的性质不难发现,任何一个数字异或它自己其结果都等于0。所以,对于本题中的数组元素而言,如果从头到尾依次异或每一个元素(即数组中所有数字进行异或),那么异或运算的结果自然就是那个只出现奇数次的数字
,因为出现偶数次的数字会通过异或运算全部消掉。
代码实现:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2020/1/27 19:27
# @Author : buu
# @Software: PyCharm
# @Blog :https://blog.csdn.net/weixin_44321080
def get2Num(arr):
if arr == None or len(arr) < 1:
print('参数不合理!')
return
result = 0
position = 0
i = 0
while i < len(arr):
# 首先对所有数组元素进行异或
result ^= arr[i]
i += 1
tmpResult = result # 临时保存异或的结果
# 找出异或结果中其中一个位值为1的位数(如1100,位值为1的位数为2和3)
i = result
while i & 1 == 0:
position += 1
i = i >> 1
i = 1
while i < len(arr):
# 异或的结果与所有第position位为1的数异或,结果一定
# 是出现依次的两个数中其中一个
if ((arr[i] >> position) & 1) == 1:
result ^= arr[i]
i += 1
print('result1:', result)
print('result2:', result ^ tmpResult)
if __name__ == '__main__':
arr = [3, 5, 6, 6, 5, 7, 2, 2]
get2Num(arr)
结果:
算法性能分析:
时间复杂度为O(n);
end