1. 程式人生 > >leetcode【260】Single Number III

leetcode【260】Single Number III

寫在最前面:

當然可以通過遍歷查詢,但是時間複雜度太高,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:

  1. The order of the result is not important. So in the above example, [5, 3] is also correct.
  2. 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]