1. 程式人生 > 其它 >【陣列】力扣645:錯誤的集合

【陣列】力扣645:錯誤的集合

集合 s 包含從 1 到 n 的整數。不幸的是,因為資料錯誤,導致集合裡面某一個數字複製了成了集合裡面的另外一個數字的值,導致集合丟失了一個數字並且有一個數字重複
給定一個數組 nums 代表了集合 S 發生錯誤後的結果。
請你找出重複出現的整數,再找到丟失的整數,將它們以陣列的形式返回。
示例1:

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

示例2:

輸入:nums = [1,1]
輸出:[1,2]

可能用到的函式

  1. sum(iterable[, start]) 求和
    其中,中括號[]表示可省略的元素。
    iterable -- 可迭代物件,如:列表、元組、集合。
    start -- 指定相加的引數,如果沒有設定這個值,預設為0。
    e.g.
    >>>sum([0,1,2])
    3
    >>> sum((2, 3, 4), 1) # 元組計算總和後再加 1 10
    >>> sum([0,1,2,3,4], 2) # 列表計算總和後再加 2 12
  2. list() 把元組換成列表

自以為是的錯誤答案:

class Solution:
    def findErrorNums(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            if nums[i+1] - nums[i] == 0:
                a = nums[i]
            elif nums[i+1] - nums[i] != 1:
                b = nums[i] + 1
        return [a, b]

編碼也不對,if nums[i+1] - nums[i] == 0: 為什麼不對呢??
而且也沒有考慮一種特殊情況:如果丟失的數字是 1 或 n。

一行程式碼解決問題:

class Solution:
    def findErrorNums(self, nums: List[int]) -> List[int]:
        # 列表list從1開始計數,陣列從0,所以列表範圍是(1, len(num)+1)
        return [sum(nums) - sum(set(nums)), sum(list(range(1, len(nums) + 1))) - sum(set(nums))]

官方解答3種方法:

  • 排序
    將陣列排序之後,比較每對相鄰的元素,即可找到錯誤的集合。
    尋找重複的數字較為簡單,如果相鄰的兩個元素相等,則該元素為重複的數字。
    尋找丟失的數字相對複雜,可能有以下兩種情況:
    如果丟失的數字大於 1 且小於 n,則一定存在相鄰的兩個元素的差等於 2,這兩個元素之間的值即為丟失的數字;
    如果丟失的數字是 1 或 n,則需要另外判斷。
    為了尋找丟失的數字,需要在遍歷已排序陣列的同時記錄上一個元素,然後計算當前元素與上一個元素的差。考慮到丟失的數字可能是 1,因此需要將上一個元素初始化為 0。
    當丟失的數字小於 n 時,通過計算當前元素與上一個元素的差,即可得到丟失的數字;
    如果nums[n-1] != n,則丟失的數字是 n。
    時間複雜度:O(nlogn),其中 n 是陣列 nums 的長度。排序需要O(nlogn) 的時間,遍歷陣列找到錯誤的集合需要 O(n) 的時間,因此總時間複雜度是 O(nlogn)。
    空間複雜度:O(logn),其中 n 是陣列 nums 的長度。排序需要 O(logn) 的空間。

  • 雜湊表
    重複的數字在陣列中出現 2 次,丟失的數字在陣列中出現 0 次,其餘的每個數字在陣列中出現 1 次。因此可以使用雜湊表記錄每個元素在陣列中出現的次數,然後遍歷從 1 到 n 的每個數字,分別找到出現 2 次和出現 0 次的數字,即為重複的數字和丟失的數字。
    時間複雜度:O(n),其中 n 是陣列 nums 的長度。需要遍歷陣列並填入雜湊表,然後遍歷從 1 到 n 的每個數尋找錯誤的集合。
    空間複雜度:O(n),其中 n 是陣列 nums 的長度。需要建立大小為 O(n) 的雜湊表。

  • 位運算
    使用位運算,可以達到 O(n) 的時間複雜度和 O(1) 的空間複雜度。
    重複的數字在陣列中出現 2 次,丟失的數字在陣列中出現 0 次,其餘的每個數字在陣列中出現 1 次。由此可見,重複的數字和丟失的數字的出現次數的奇偶性相同,且和其餘的每個數字的出現次數的奇偶性不同。如果在陣列的 n 個數字後面再新增從 1 到 n 的每個數字,得到 2n 個數字,則在 2n 個數字中,重複的數字出現 3 次,丟失的數字出現 1 次,其餘的每個數字出現 2 次。根據出現次數的奇偶性,可以使用異或運算求解。

作者:LeetCode-Solution
連結:https://leetcode-cn.com/problems/set-mismatch/solution/cuo-wu-de-ji-he-by-leetcode-solution-1ea4/