(python刷題)leetcode 第18題:四數之和

題目在leetcode上的鏈接爲:
https://leetcode-cn.com/problems/4sum/

題目描述
在這裏插入圖片描述
解題思路
這一題與第15題 三數之和 的解題思路類似。先對數組進行從小到大的排序,然後使用兩重循環遍歷數組,再使用雙指針遍歷一遍即可。
具體步驟爲:

  • 首先如果 nums 爲 None,或者 nums 長度小於4,那麼返回空列表
  • 將 nums 按照從小到大進行排序
  • 使用變量 i 循環遍歷 nums:
    • 如果 i>0 且 nums[i]=nums[i-1],說明前一步中已經考慮了這一步可能存在的四個數的結果,那麼 continue 不執行之後的代碼,以此進行去重操作(第一次去重)
    • 使用變量 j 循環遍歷 nums[i+1:]
      • 如果 j>i+1 且 nums[j]=nums[j-1],則 continue 不執行之後的代碼,以此進行去重操作(第二次去重)
      • 令左指針 left 爲 j+1,右指針 right 爲 len(nums)-1
      • 以 left<right 作爲判斷條件進入循環:
        • 如果 nums[i]+nums[j]+nums[left]+nums[right] 等於 target:
          • 將找到的四個數添加到結果中
          • 循環判斷如果左右指針位置的數等於它門下一個位置的數時,就將指針移到下一個位置進行去重操作 (第三次去重)
          • 將左右指針都移到下一個位置重新找下一個可能的結果
        • 如果 nums[i]+nums[j]+nums[left]+nums[right] 小於 target,說明太小了,則將左指針向右移動一步
        • 如果 nums[i]+nums[j]+nums[left]+nums[right] 大於 target,說明太大了,則將右指針向左移動一步

ps: 要注意算法中標明的三次去重操作,其中第一次和第三次的去重操作與 三數之和 中的一樣,特別注意第二次去重操作中的條件 j>i+1,因爲當 j=i+1 時,nums[j-1]=nums[i],此時比較的 nums[j]=nums[j-1]=nums[i] 是將 i 與 j 位置的數進行比較,但我們需要比較的是 j 位置的數與它之前自己走過的前一步的數是否相同,所以需要條件 j>i+1,讓 j 與 i 不相鄰時再比較決定是否對 j 進行去重操作

複雜度分析:
排序操作的時間複雜度爲 o(nlog(n)),三重循環的複雜度爲 o(n3),由於這兩步操作是順序執行,所以總的時間複雜度爲 o(nlog(n))+o(n3),即爲 o(n3)。
由於只需要常數級的存儲空間,所以空間複雜度爲 o(1)

python代碼

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        if not nums or len(nums) < 4:
            return []
        nums.sort()
        if (target >= 0 and nums[0] > target) or (target < 0 and nums[len(nums) - 1] < target):
            return []
        res = []
        for i in range(len(nums)):
            if target >= 0 and nums[i] > target:
                return res
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            for j in range(i + 1, len(nums)):
                if j > i + 1 and nums[j] == nums[j - 1]:
                    continue
                left = j + 1
                right = len(nums) - 1
                while left < right:
                    if nums[i] + nums[j] + nums[left] + nums[right] == target:
                        res.append([nums[i], nums[j], nums[left], nums[right]])
                        while left < right and nums[left] == nums[left + 1]:
                            left += 1
                        while left < right and nums[right] == nums[right - 1]:
                            right -= 1
                        left += 1
                        right -= 1
                    elif nums[i] + nums[j] + nums[left] + nums[right] > target:
                        right -= 1
                    else:
                        left += 1
        return res
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章