136只出现一次的数字
题目:
给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
示例 1 :
输入: nums = [2,2,1]
输出: 1
示例 2 :
输入: nums = [4,1,2,1,2]
输出: 4
示例 3 :
输入: nums = [1]
输出: 1
大体思路
拿到这道题,第一步想的当然是遍历,但是这是时间复杂度较高的一个思路。后面看到了提示里的借助按位异或的方式,才有了以下思路,很妙很妙~
首先让我们明确一下,在计算机的二进制计算中,异或的计算方法是相异为一,相同为零。
我们将思路扩展,不止局限于单一的0,1。我们将一个具体的数字转换为二进制进行计算,比如4和1,4可以变为0100,1可以变为0001,那么按位异或0^0=0,1^0=1,0^0=0,0^1=1。所以最后的结果为0101,也就是5,所以4^1=5。
知道了这个之后,我们还需要明确一点就是任何数和自己按位异或都为0(因为各个位数都一样),任何数和0按位异或都是自己。
这是我们思路的关键,既然除过一个数之外其他的都会出现两次,那么我们将其按位异或就会为0,然后0跟这个只出现一次的数字按位异或就会是这个数字自己。
并且异或的运算还遵循交换律和结合律,也就是说,我们不用担心异或顺序的问题。
实现代码
func singleNumber(nums []int) int {
result := 0
for _, num := range nums {
result ^= num
}
return result
}
// 时间复杂度:O(n),只需遍历一次
// 空间复杂度:O(1),只使用了一个变量
此处对于小白来说还需要解释一下range这个关键字,这里的range返回的是索引和值,但是在此处我们只需要值,索引要忽略所以for的循环条件写为: _, num := range nums。第一个_为忽略索引的意思,此处只接受了后面的值。