LeetCode Notes_#18 4Sum
阿新 • • 發佈:2018-11-15
LeetCode Notes_#18 4Sum
LeetCodeContents
題目
Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
The solution set must not contain duplicate quadruplets.
Example:
Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.
A solution set is:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
思路和解答
思路
問題的內容跟之前的2sum,3sum都是很相似的,僅僅是修改了元素的個數,增加了複雜度(不可以再使用暴力迴圈的方式,而是要用盡可能少的指標,儘可能少的list訪問次數去達成目標)
- 2sum,兩個指標兩層迴圈,遍歷所有可能的兩兩組合形式
- 3sum,3sumcloest,三個指標,第一個指標遍歷所有元素,後面兩個指標從左右向中間移動,這並沒有遍歷到所有情況,但是不會漏掉需要的情況(前提是提前對list排序,然後根據結果的大小動態移動左右指標)
- 4sum是怎樣呢?一定還是需要四個指標的,主要問題在於如何去優化指標遍歷元素的方式。
解答
#第一版,通過了最簡單的case,但是沒有考慮到nums裡邊數字出現重複的情況
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
res=[]
nums.sort()
for i in range(len(nums)-3):
for j in range(i+1,len(nums)-2):
l=j+1
r=len(nums)-1
while(l<r):
sum=nums[i]+nums[j]+nums[l]+nums[r]
if sum<target:
l+=1
if sum>target:
r-=1
if sum==target:
res.append([nums[i],nums[j],nums[l],nums[r]])
l+=1
r-=1
return res
#第二版,目的是去除重複,在pycharm上面執行結果沒毛病,但是不知道為什麼一樣的程式碼在leetcode上面執行結果不一樣...
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
res=[]
nums.sort()
for i in range(len(nums)-3):
if i>0 and nums[i]==nums[i-1]:
continue
for j in range(i+1,len(nums)-2):
if j>0 and nums[j]==nums[j-1]:
continue
l=j+1
r=len(nums)-1
while(l<r):
sum=nums[i]+nums[j]+nums[l]+nums[r]
if sum<target:
l+=1
if sum>target:
r-=1
if sum==target:
res.append([nums[i],nums[j],nums[l],nums[r]])
while l < r and nums[l] == nums[l + 1]: # 兩個while語句用來快速移動指標,直到沒有出現相鄰重複數字
l += 1
while l < r and nums[r] == nums[r - 1]:
r -= 1
l+=1
r-=1
return res
#最後還是看一下討論區大佬的程式碼吧,使用了遞迴的方式,可以適用於任意的N-sum的情況
def fourSum(self, nums, target):
def findNsum(l, r, target, N, result, results):
if r-l+1 < N or N < 2 or target < nums[l]*N or target > nums[r]*N: # early termination
return
if N == 2: # two pointers solve sorted 2-sum problem
while l < r:
s = nums[l] + nums[r]
if s == target:
results.append(result + [nums[l], nums[r]])
l += 1
while l < r and nums[l] == nums[l-1]:
l += 1
elif s < target:
l += 1
else:
r -= 1
else: # recursively reduce N
for i in range(l, r+1):
if i == l or (i > l and nums[i-1] != nums[i]):
findNsum(i+1, r, target-nums[i], N-1, result+[nums[i]], results)
nums.sort()
results = []
findNsum(0, len(nums)-1, target, 4, [], results)
return results
遞迴的過程大概是這樣的:
一個N-sum問題可以不斷地轉化為(N-1)-Sum問題,比如說要求4-sum==0
- 假如先確定第一個數字-2,那麼就轉化為去找3-sum==2,這時result=[-2],N=3
- 3-sum=2,假如確定第二個數字是0,那麼去找2-sum==2,這時result=[-2,0],N=2
- N=2就進入2sum的處理方式,直接找到2-sum==2的結果[0,2],這時results.append(result+[0,2]),相當於對results添加了一個[-2,0,0,2]
- 中間如果遇到肯定不可能的情況就直接pass,以此類推就可以解決任意N-sum問題