LeetCode Everyday:堅持價值投資,做時間的朋友!!!
題目:
給定一個包含n
個整數的數組nums
和一個目標值target
,判斷nums
中是否存在四個元素 a,b,c 和 d ,使得 a + b + c + d 的值與target
相等?找出所有滿足條件且不重複的四元組。
注意:答案中不可以包含重複的四元組
示例:
- 示例 1:
給定數組 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 滿足要求的四元組集合爲: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
代碼
方法一: 雙指針
執行用時:100 ms, 在所有 Python3 提交中擊敗了86.85%的用戶
內存消耗:13.6 MB, 在所有 Python3 提交中擊敗了6.52%的用戶
class Solution:
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
nums.sort()
n = len(nums)
res = []
p = 0 # p, k, i, j
while p < n - 3: # 文中提到的條件1和條件2,可以直接跳過
if nums[p] + 3 * nums[p + 1] > target: break
if nums[p] + 3 * nums[-1] < target:
while p < n - 4 and nums[p] == nums[p + 1]: p += 1
p += 1
continue
k = p + 1
while k < n - 2: # k 和 p 的判斷是一樣的
if nums[p] + nums[k] + 2 * nums[k + 1] > target: break
if nums[p] + nums[k] + 2 * nums[-1] < target:
while k < n - 3 and nums[k] == nums[k + 1]:
k += 1
k += 1
continue
i = k + 1
j = n - 1
new_target = target - nums[p] - nums[k]
while i < j:
if nums[i] + nums[j] > new_target: j -= 1
elif nums[i] + nums[j] < new_target: i += 1
else:
res.append([nums[p],nums[k],nums[i],nums[j]])
i += 1
j -= 1
while i < j and nums[i] == nums[i - 1]: i += 1 # 避免結果重複
while i < j and nums[j] == nums[j + 1]: j -= 1 # 避免結果重複
while k < n - 3 and nums[k] == nums[k + 1]: k += 1
k += 1
while p < n - 4 and nums[p] == nums[p + 1]: p += 1
p += 1
return res
"""
For Example: input: nums = [1, 0, -1, 0, -2, 2] target = 0
output: [
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
"""
nums = [1, 0, -1, 0, -2, 2]
target = 0
solution = Solution()
result = solution.fourSum(nums, target)
print('輸出爲:', result)
方法二: 哈希表
執行用時:124 ms, 在所有 Python3 提交中擊敗了78.68%的用戶
內存消耗:17.8 MB, 在所有 Python3 提交中擊敗了6.52%的用戶
class Solution:
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
N = len(nums)
if N < 4:
return []
# use set to deduplicate
res = set()
nums.sort()
# sum:[(index1, index2)]
table = {}
for i in range(N - 1):
for j in range(i + 1, N):
s = nums[i] + nums[j]
if target - s in table:
for tmp in table[target - s]:
if tmp[1] < i:
# use tuple since it is hashable
res.add((nums[tmp[0]], nums[tmp[1]], nums[i], nums[j]))
if s not in table:
table[s] = []
table[s].append((i, j))
# convert set to list
ans = []
for r in res:
ans.append(list(r))
return ans
"""
For Example: input: nums = [1, 0, -1, 0, -2, 2] target = 0
output: [
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
"""
nums = [1, 0, -1, 0, -2, 2]
target = 0
solution = Solution()
result = solution.fourSum(nums, target)
print('輸出爲:', result)
方法三: 深度優先搜索
執行用時:40 ms, 在所有 Python3 提交中擊敗了65.51%的用戶
內存消耗:13.8 MB, 在所有 Python3 提交中擊敗了5.41%的用戶
class Solution:
def letterCombinations(self, digits):
"""
:type digits: str
:rtype: List[str]
"""
return self.nSum(nums, target, 4)
def nSum(self, nums, target, n):
def dfs(pos, cur, n, target):
if n == 2:
j = pos
k = len(nums) - 1
while j < k:
sum = nums[j] + nums[k]
if sum < target:
j += 1
elif sum > target:
k -= 1
else:
solution = cur[:] + [nums[j], nums[k]]
ans.append(solution)
while j < k and nums[j] == nums[j+1]:
j += 1
while j < k and nums[k] == nums[k-1]:
k -= 1
j += 1
k -= 1
return
i = pos
while i < len(nums) - n + 1:
# 剪枝的一種情況
if nums[i] * n > target or nums[-1] * n < target:
break
# 排除重複數字
if i > pos and nums[i] == nums[i-1]:
i += 1
continue
cur.append(nums[i])
dfs(i+1, cur, n-1, target-nums[i]) # 回溯
cur.pop()
i += 1
ans = []
nums.sort()
dfs(0, [], n, target)
return ans
"""
For Example: input: digits = "23"
output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]
"""
digits = "23"
solution = Solution()
result = solution.letterCombinations(digits)
print('輸出爲:', result)
參考
- https://leetcode-cn.com/problems/4sum/solution/shuang-zhi-zhen-gao-su-jie-fa-by-ml-zimingmeng/
- https://leetcode-cn.com/problems/4sum/solution/fei-shuang-zhi-zhen-er-ha-xi-biao-jiang-4shu-zhi-h/
- https://leetcode-cn.com/problems/4sum/solution/shen-du-you-xian-sou-suo-yi-ci-xing-jie-jue-nsum-9/