https://leetcode.com/problems/single-number/submissions/
题目描述:
Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
要完成的函数:
def singleNumber(self, nums: List[int]) -> int:
思路:
1、给定一组数,这组数中除了有一个元素只出现一次,其他元素都出现了两次,要求输出这个只出现一次的元素的值。
2、时间复杂度O(n),也就是只能从头到尾遍历一次;空间复杂度O(1),只能使用常数级的空间。
3、照这道题目的要求来看,既不能常规做法的定义一个数组,记录每个数出现了几次;也不能双重循环找到出现两次的数,然后把它们都删掉,接着继续遍历,直到最后只剩下出现一次的数。所以这道题目要求只能遍历一遍,那就只能从数学上寻找方法了。
4、这道题目笔者本人想了很长时间,都不知道采用什么数学方法好,直到在discuss中看到大神采用异或(XOR)的做法……以下举例说明为什么异或能够处理这道问题。
举例说明:
先说明一点,所有整数在计算机中都采用二进制的表示方法。以下举两个例子:
1、数组为1、1、2,在计算机中表示为0001,0001,0010,那么0001^0001=0000,接着0000^0010=0010。最后得到的结果是2,也就是2是只出现一次的数。
2、数组为1、2、1,在计算机中表示为0001,0010,0001,那么0001^0010=0011,接着0011^0001=0010。最后得到的结果是2,也就是2是只出现一次的数。
数学原理:
异或是两个相同的数则异或结果为0,两个不同的数异或结果为1,并且异或满足交换律和结合律,所以我们可以得到这样的结论:A^B^C^B^D^C^A=D。
异或其实是“记录”了所有出现过的数,只要你第二遍出现,异或结果就会为0,直到一个只出现一次的数,那么异或结果最终为这个只出现一次的数的数值。
异或能够记录曾经出现过的数,然后一直在等待第二遍出现,来异或为0。如果一直没有第二遍出现,数组中全都是只出现一遍的数,那么最终结果会是很奇怪的。各位同学不妨试试。
代码:
class Solution:
def singleNumber(self, nums: List[int]) -> int:
start = nums[0]
for i in range(1, len(nums)):
nums[0] ^= nums[i]
return nums[0]