题目描述:
- 一个整型数组里只有一个数字出现里只出现一次,其他数字都出现两次,请写出程序找出只出现一次的数字。
- 一个整型数组里除了两个数字之外,其他的数字都出现两次。请写出程序找出这两个只出现一次的数字。
方法一:
对两题都适用。
利用字典(map),map的key是数组中的数字,value是此数字出现的次数。需要遍历两次,第一次遍历数组,初始化字典,第二次遍历字典找出两个只出现一次的值。
class Solutions {
func findNumbers(_ inputNums: [Int]) -> Int {
var result: Int = 0
var map: [Int: Int] = [:]
for item in inputNums {
if let value = map[item] {
map[item] = value + 1
}
else {
map[item] = 1
}
}
for (item, value) in map {
if value == 1 {
result = item
break
}
}
return result
}
}
let num = Solutions().findNumbers([1, 1, 2])
print(num)
方法二:
限定条件:时间复杂度为O(n),空间复杂度为O(1),这样的话,方法一就不满足了。
来复习下位运算中操作符:异或:两个数字异或之后相同为0,一个数字和0异或还是他本身。
异或的运算法则:
a ^ a = 0
a ^ 0 = a
a ^ b = b ^ a
a ^ b ^ a = b
// 若x是二进制数0101,y是二进制数1011
x ^ y = 1110
// 相同为0,不同为1
所以,对题目1来说,当只有一个数出现一次时,把数组中所有元素依次异或,最后的结果就是落单的数。
class Solutions {
func findNumbers(_ inputNums: [Int]) -> Int {
var result: Int = 0
for item in inputNums {
result = result ^ item
}
return result
}
}
let num = Solutions().findNumbers([1, 1, 2])
print(num)
再来看题目2,一个数组中有两个数字只出现了一次的情况,假设是A、B两个数字只出现一次,最后的结果肯定是A和B异或的结果,将结果转为二进制,二进制中的1代表的是A和B不同的位。取到A和B中第一个不同的位(即第一个1所在的位数),例如第二位,然后按二进制第二位为1把原数组进行分组。然后会有两个数组:由于是A、B异或结果为1,所有A、B的二进制的第二位肯定不一样,即A、B会分在不同的数组里。而且对于同一组来说,同一组里的其他元素肯定都是偶数出现的,因为只有两个数字只出现了一次。所有最终对于每一组来说,就有变成了题目1.
class Solutions {
func isBit1(target: Int, index: Int) -> Bool {
return ((target >> index) & 1) == 1
}
func findNumbers(_ inputNums: [Int]) -> [Int] {
var nums1: [Int] = [] // 存储第X位是1的数组
var nums2: [Int] = [] // 存储第X位非1的数组
if inputNums.count == 2 {
nums1.append(inputNums[0])
nums2.append(inputNums[1])
}
var tempResult = 0 // tempResult结果肯定是只出现一次的两个数的异或结果
for item in inputNums {
tempResult = tempResult ^ item
}
// 遍历tempResult的二进制,找到第一个为1的位
let tempStr = String(tempResult, radix: 2)
var firstIndex = 0
for charS in tempStr {
if charS == "1" {
break
}
firstIndex += 1
}
var firstValue = 0
var secondValue = 0
for item in inputNums {
if isBit1(target: item, index: firstIndex) {
firstValue = firstValue ^ item
}
else {
secondValue = secondValue ^ item
}
}
return [firstValue, secondValue]
}
}
let num = Solutions().findNumbers([1, 1, 2, 3])
print(num)