元素重复三次的数组中查找重复一次的元素
题目:
给定一个大数组,它里面除了一个元素外,其他元素都重复了三次,要求在空间复杂度为O(1), **时间复杂度为O(n)**的约束下,查找到只重复了一次的元素。
意思就是说:这意味着算法必须对数组遍历1次就要找出给定元素。
解题思路
参考位图算法,
- 声明两个变量 firstAppear(FA) 和 secondAppear(SA) ,初始值均为零
- 当某一位第一次出现1时,FA的该位值为1
- 当想通位第二次出现1时,FA该位值为0,SA该位值为1
- 当想通位第三次出现1时,FA该位值为0,SA该位值为0
这样,出现三次的数值都会被过滤掉,而只出现一次的数值会留在FA中。
假设 E 为元素某位的值,我们需要有 newFA 和 newSA 来临时储存新的值,按照结果推到出关于 newFA 的如下表格:
SA/E | 0/0 | 0/1 | 1/0 | 1/1 |
---|---|---|---|---|
FA=0 | 0 | 1 | 0 | 0 |
FA=1 | 1 | 0 | x | x |
我们需要由这个表格推导出 newFA 与 FA、SA、E的位运算关系:
- SA 为0时,缩小了取值范围,并覆盖了 newFA==1 的范围,即得出一个 & 运算因子 ~SA
- 当 FA/E 为 0/1 或 1/0 时,进一步缩小了取值范围,且恰好与所有 newFA==1 的范围匹配,得出 & 运算因子 FA^E
所以newFA 与 FA、SA、E的位运算关系为 newFA = ~SA & (FA^E)
newSA 的如下表格:
FA/E | 0/0 | 0/1 | 1/0 | 1/1 |
---|---|---|---|---|
SA=0 | 0 | 0 | 0 | 1 |
SA=1 | 1 | 0 | x | x |
由这个表格推导 newSA 与 FA、SA、E的位运算关系:
- SA 与 E 相反时,缩小了取值范围,并覆盖了 newSA==1 的范围,即得出一个 & 运算因子 SA^E
- 当 FA/E 为 0/0 或 1/1 时,进一步缩小了取值范围,且恰好与所有 newSA==1 的范围匹配,得出 & 运算因子 ~(FA^E)
所以newFA 与 FA、SA、E的位运算关系为 newSA = (SA^E) & ~(FA^E)
之后再把 FA = newFA 和 SA = newSA 即可。
PS:推导的原则基本上就是不断缩小取值范围,直至完全匹配,然后用 & 连接运算因子。
实现代码
Swift code:
let arr = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4];
var FA = 0
var SA = 0
var newFA = 0
var newSA = 0
for E in arr{
newFA = ~SA & (FA^E)
newSA = (SA^E) & ~(FA^E)
FA = newFA
SA = newSA
}
print(FA)
//4
print(SA)
//0
PS:若是查找该数组中仅有的重复两次的元素,SA即是
代码地址:https://github.com/sinianshou/EGSwiftLearning