1. 程式人生 > >leetcode 287. 尋找重複數【Medium】【陣列】 && 劍指Offer 面試題3 題目2:不修改陣列找出重複的數字

leetcode 287. 尋找重複數【Medium】【陣列】 && 劍指Offer 面試題3 題目2:不修改陣列找出重複的數字

       這道題leetcode和劍指Offer題目略有不同。leetcode說陣列中的重複數可能不止一個,但是結果要求返回一個就行;劍指Offer上說只有一個重複的數,但是重複的次數不一定。兩個題目的共性就是隻需要返回一個重複的數即可。

leetcode 題目:

給定一個包含 n + 1 個整數的陣列 nums,其數字都在 1 到 之間(包括 1 和 n),可知至少存在一個重複的整數。假設只有一個重複的整數,找出這個重複的數。

示例 1:

輸入: [1,3,4,2,2]
輸出: 2

示例 2:

輸入: [3,1,3,4,2]
輸出: 3

說明:

  1. 不能更改原陣列(假設陣列是隻讀的)。
  2. 只能使用額外的 O(1) 的空間。
  3. 時間複雜度小於 O(n2) 。
  4. 陣列中只有一個重複的數字,但它可能不止重複出現一次。

思路:

由於不能使用額外的空間,不能使用記錄或統計出現的數,又不能破壞陣列結構,不能通過排序來判斷相鄰數是否相等。

       1.暴力法,兩層迴圈,時間複雜度O(n2)太高。

       2.用集合儲存遍歷值,時間複雜度n,但有額外空間開銷。

       3.歸併排序,時間複雜度nlogn,空間複雜度 O(1),但破壞陣列結果。

       4.二分法,因為數出現在[1,n]。所以統計[1-n/2]的數,如果出現小於等於n/2的數個數超過n/2,[1-n/2]數中有重複的數,繼續通過二分減少搜尋範圍,這裡的時間複雜度為nlogn。


程式碼:

class Solution:
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        low,high = 1,len(nums)
        while low < high:
            count = 0
            mid = (low + high)//2
            for item in nums:
                if item <= mid:
                    count += 1
            if count > mid:
                high = mid
            else:
                low = mid + 1
        return low