1. 程式人生 > 實用技巧 >LeetCode 350. 兩個陣列的交集 II | Python

LeetCode 350. 兩個陣列的交集 II | Python

350. 兩個陣列的交集 II


題目來源:力扣(LeetCode)https://leetcode-cn.com/problems/intersection-of-two-arrays-ii

題目


給定兩個陣列,編寫一個函式來計算它們的交集。

示例 1:

輸入: nums1 = [1,2,2,1], nums2 = [2,2]
輸出: [2,2]

示例 2:

輸入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
輸出: [4,9]

說明:

  • 輸出結果中每個元素出現的次數,應與元素在兩個陣列中出現的次數一致。
  • 我們可以不考慮輸出結果的順序。

進階:

  • 如果給定的陣列已經排好序呢?你將如何優化你的演算法?
  • 如果 nums1 的大小比 nums2 小很多,哪種方法更優?
  • 如果 nums2 的元素儲存在磁碟上,磁碟記憶體是有限的,並且你不能一次載入所有的元素到記憶體中,你該怎麼辦?

解題思路


思路:雜湊表,雙指標

先看題目,結合示例 1 和第一條說明【輸出結果中每個元素出現的次數,應與元素在兩個陣列中出現的次數一致】,由此我們知道,同一個數字在兩個陣列中,都有可能出現多次。

雜湊表

在這裡,我們先說雜湊表的思路。我們可以使用雜湊表來儲存每個數字出現的次數。在這裡,我們要求兩個陣列的交集,那麼這裡數字出現的次數取決於兩個陣列中出現次數較小的部分。

在這裡,我們可以考慮對較短的陣列進行遍歷,在雜湊表中記錄數字以及對應出現的次數。然後再遍歷另外一個數組,如果數字存在於雜湊表中,那麼將數字新增到結果列表中,然後將雜湊表對應數字的次數減 1。(這裡選擇對較短陣列進行遍歷存雜湊表,考慮的是降低空間複雜度。)

關於雜湊表思路的圖解如下(示例 2):

具體實現程式碼見【程式碼實現 # 雜湊表】

雙指標

在題目後面的進階當中第一個問題,提到如果陣列都是已經排好序的,該如何優化演算法?

在這裡,我們可以考慮使用雙指標的方法。雙指標思路的演算法大致如下:

  • 首先定義雙指標,分別指向兩個陣列的首元素。
  • 開始比較雙指標指向的元素,對以下的情況進行處理:
    • 如果兩個元素不相等,指標指向元素較小的向後移動;
    • 如果兩個元素相等,則將元素新增到結果列表中,然後兩個指標同時向後移動。
  • 當任意指標到達末尾時,結束遍歷。

關於雙指標思路的圖解如下(示例 2):

具體實現程式碼見【程式碼實現 # 雙指標】

在這裡,針對進階的第三個問題

大致的說明下。如果出現 nums2 的元素儲存在磁碟上,磁碟記憶體有限,無法一次載入所有的元素到記憶體中。那麼此時想要快速進行排序,則不太可能,所以建議使用雜湊表的思路。針對雜湊表的思路,陣列涉及的是查詢操作,可以考慮讀取部分資訊進行處理。

程式碼實現


# 雜湊表
class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # 針對較短陣列進行遍歷將元素存於雜湊表中
        # 保證前面的陣列較短
        if len(nums1) > len(nums2):
            self.intersect(nums2, nums1)
        
        hash_map = {}

        for num in nums1:
            if num not in hash_map:
                hash_map[num] = 0
            hash_map[num] += 1
        
        ans = []

        for num in nums2:
            # 檢視是否存在於雜湊表中
            count = hash_map.get(num, 0)
            # 元素存在於雜湊表中,則新增入結果列表中
            # 然後將雜湊表對應的元素出現次數減一
            if count > 0:
                ans.append(num)
                hash_map[num]-=1
        
        return ans

# 雙指標
class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        nums1.sort()
        nums2.sort()

        p = q = 0

        ans = []
        # 任意指標到達陣列末尾,結束遍歷
        while p < len(nums1) and q < len(nums2):
            # 在這裡,先判斷指標對應元素的大小
            # 當不相等時,指標對應元素小的移動
            # 相等時,將元素放入結果列表中,同時移動指標
            if nums1[p] > nums2[q]:
                q+=1
            elif nums1[p] < nums2[q]:
                p += 1
            else:
                ans.append(nums1[p])
                p += 1
                q += 1
        
        return ans

實現結果


雜湊表|實現結果

雙指標|實現結果

歡迎關注


公眾號 【書所集錄