版权声明:本文为博主原创文章,未经允许,不得转载,如需转载请注明出处 https://blog.csdn.net/ssjdoudou/article/details/83931392
写在最前面:
当然可以通过遍历查找,但是时间复杂度太高,leetcode肯定通不过。
然后我们要研究异或。
leetcode【260】Single Number III
Given an array of numbers nums
, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
Example:
Input:[1,2,1,3,2,5]
Output:[3,5]
Note:
- The order of the result is not important. So in the above example,
[5, 3]
is also correct. - Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
首先给出很常规的解法:
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
length = len(nums)
res = []
newnum = []
for i in range(length):
for j in range(i+1,length):
if nums[i] == nums[j]:
res.append(nums[j])
if nums[i] not in res:
newnum.append(nums[i])
return newnum
借鉴一下大神的思路吧,前方高能!
关键思路是,只有两个数不同,那么我们需要一遍异或,这个异或的值是什么呢,是两个不同的数的异或值,然后我们用mark标记这这个异或值其中哪一位是1,因为这个异或值只有两个1,这两个1区分了不同的两个数。假设3,5是不同的数,异或为6,即0110,那么我们就可以拿0100和0010去遍历所有数,进行与操作,与操作的规则是只有两个都为1,结果才为1,其余都是0。只要遍历结果为0000,即为0,那么我们就找到了这个数。
而大神的代码效率高在于他找到第一个为1的数,即0010后,没有再找下一个,那么这个0010遍历所有数后只能找到一个不同的数,神奇的在于,除去一个不同的数,假设是3,那么剩下所有的数相异或的结果就是另一个不同的数,5!
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
xor = 0
num1, num2 = 0, 0
for num in nums:
xor ^= num
mask = 1
while xor & mask == 0:
mask = mask << 1
for num in nums:
if num & mask == 0:
num1 ^= num
else:
num2 ^= num
return [num1, num2]
下面是我理解了思路自己写的,即使关键部分用了异或和与运算,还是在leetcode上超时。 主要是因为我找到两个mark,分别去遍历所有数,导致时间复杂度高。
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
xor = 0
num1, num2 = 0, 0
if len(nums) == 2:
return nums
for num in nums:
xor ^= num
mask1 = 1
while xor & mask1 == 0:
mask1 = mask1 << 1
mask2 = mask1 << 1
while xor & mask2 == 0:
mask2 = mask2 << 1
for num in nums:
if num & mask1 == 0:
num1 ^= num
elif num & mask2 == 0:
num2 ^= num
return [num1, num2]