iT邦幫忙

0

leetcode with python:18. 4Sum

  • 分享至 

  • xImage
  •  

題目:

Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that:

0 <= a, b, c, d < n
a, b, c, and d are distinct.
nums[a] + nums[b] + nums[c] + nums[d] == target
You may return the answer in any order.

給定一陣列和目標值(target)
回傳陣列中所有取四數相加為target的可能,且不能包含重複的可能

又一題15.的類題
只要將其中一值固定,就相當於在找3sum
再將其中一值固定,就相當於在找2sum

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        if len(nums)<4:
            return []
        
        ans=[]
        nums=sorted(nums)
        
        for i in range(len(nums)-3):
            for j in range(i+1,len(nums)-2):
                aim=target-nums[i]-nums[j]
                l=j+1
                r=len(nums)-1
                while l<r:
                    if nums[l]+nums[r]>aim:
                        r=r-1
                    elif nums[l]+nums[r]<aim:
                        l=l+1
                    else:
                        if [nums[i],nums[j],nums[l],nums[r]] not in ans:
                            ans.append([nums[i],nums[j],nums[l],nums[r]])
                        l=l+1
                        while l<r and nums[l-1]==nums[l]:
                            l=l+1
            
        return ans

類似的操作就不再贅述,詳細可看15.
讓陣列的值輪流當固定值,對固定值右側的元素做3sum操作
但多層的迴圈讓加速程式的機制難以撰寫
所以上述的版本我並未添加加速機制,因此效能也較低
最後執行時間983ms(faster than 62.98%)

討論區有人使用遞迴實作,不僅讓程式看起來更有條理
也讓加速機制的撰寫更為方便
此解法不只能用在4sum,5sum,6sum都能用相同的函式解決

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums.sort()
        ans=[]
        temp=[]
        
        def ksum(target,start,k):
            if len(nums) < k or k < 2 or target < nums[start]*k or target > nums[-1]*k:
                return
            if k!=2:
                for i in range(start,len(nums)-k+1):
                    if i>start and nums[i]==nums[i-1]:
                        continue
                    temp.append(nums[i])
                    ksum(target-nums[i],i+1,k-1)
                    temp.pop()
                return
            
            l=start
            r=len(nums)-1
            while l<r:
                if nums[l]+nums[r]<target:
                    l=l+1
                elif nums[l]+nums[r]>target:
                    r=r-1
                else:
                    ans.append(temp+[nums[l],nums[r]])
                    l=l+1
                    while l<r and nums[l-1]==nums[l]:
                        l=l+1
            
        ksum(target,0,4)
        return ans

先將陣列排序方便操作
該遞迴函式(ksum)有三個輸入值,目標值(target),起始位置(start),要求幾sum(k表ksum)
透過遞迴程式的加速機制更好制定:
當發現target < nums[start] * k 或 target > nums[-1] * k
就直接return提早結束該次遞迴

若k大於2,則將start以後的值輪流當固定值
將固定值放入temp供後續使用
接著執行ksum(target-固定值,固定值位置+1,k-1),進入下一階段
執行完將temp內的值pop掉

若k等於2,則開始用兩端指標求符合條件的組合(詳見15.)
若有找到則在ans填入temp+[nums[l],nums[r]] (即其中一種4sum組合)

函式完全結束後回傳ans
最後執行時間84ms(faster than 98.83%)

那我們下題見


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言