https://leetcode-cn.com/problems/4sum/
# -*- coding:utf-8 -*-
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
nums.sort()
res = []
# 选定a
for i in range(len(nums)):
# 选定b
if i > 0 and nums[i] == nums[i- 1]:
continue
new_target = target - nums[i]
new_nums = nums[i + 1:]
for j in range(len(new_nums) - 2):
left = j + 1
right = len(new_nums) - 1
if j > 0 and new_nums[j] == new_nums[j - 1]:
continue
while left < right:
temp = new_nums[j] + new_nums[left] + new_nums[right]
if temp == new_target:
res_list = [nums[i], new_nums[j], new_nums[left], new_nums[right]]
res_list.sort()
res.append(res_list)
left += 1
right -= 1
# 初步去重(相当于剪枝?)
while left < right and new_nums[left] == new_nums[left - 1]:
left += 1
while left < right and new_nums[right] == new_nums[right + 1]:
right -= 1
if temp > new_target:
right -= 1
if temp < new_target:
left += 1
return res
if __name__ == '__main__':
nums = [-3, -2, -1, 0, 0, 1, 2, 3]
target = 0
print(Solution().fourSum(nums, target))
思路:这道题和之前三数之和大相径庭,只不过可以把a+b+c+d=target变成b+c+d=target-a即可。同时由于需要循环a和b的值,所以在每次循环之前都要判断当前索引的ab值和上一次的一不一样(if i > 0 and nums[i] == nums[i- 1])。
思考:同时在评论中注意到了一个非常有意思的剪枝操作,就是用最大和最小可能出现的值作为剪枝,如当选定索引0为a时,计算0、1、2、3这四个数的和——也就是abcd和的理论最小值,如果不在结果范围则直接跳过、同理处理最大值。可以节约非常多的时间。
0 条评论