leetcode刷题记--> 18题解法(python解析)
题目定义
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
来源:力扣(LeetCode)
链接: leetcode_18题.
解题
本次使用4种方法,在leetcode上还有更多的方法,只能说真牛逼,真聪明。
1. 使用二分法
2. 使用二分法的优化
3. 使用递归思路
4. 在二分法的优化上继续优化
===================================================
实现
// An highlighted block
class Solution:
def fourSum(self, nums, target):
'''
三数之和的基础上变为四数之和 使用二分法
'''
nums.sort()
res = []
length = len(nums)
for i in range(length):
for j in range(i+1,length):
l = j+1
r = length-1
while l<r:
end = target-nums[i]-nums[j]-nums[r]-nums[l]
if end == 0:
res.append([nums[i],nums[j],nums[l],nums[r]])
l+=1
r-=1
while l < r and nums[l] == nums[l - 1]: # 执行的去重操作 如果左边的的数都相同就去重
l += 1
while r > l and nums[r] == nums[r + 1]: # 执行的去重操作 如果右边的的数都相同就去重
r -= 1
elif end > 0:
l += 1
else:
r -= 1
return list(set(map(tuple, res)))
def fourSum_1(self, nums, target) :
'''
第一种的优化
'''
nums.sort()
length = len(nums)
ans = []
for i in range(length):
for j in range(i + 1, length):
l, r, t = j + 1, length - 1, target - nums[i] - nums[j]
while l < r:
while l < r and t > nums[l] + nums[r]: l += 1
while l < r and t < nums[l] + nums[r]: r -= 1
if l < r and nums[l] + nums[r] == t:
ans.append([nums[i], nums[j], nums[l], nums[r]])
l += 1
return list(set(map(tuple, ans)))
def fourSum_2(self, nums, target):
'''
在三数之和的时候使用这种方法是可以的 但是四数之和就超时了
'''
import itertools
ts, bs = [i for i in set(list(itertools.combinations(nums, 4))) if
sum(i) == target], {} # 求出所有的组合 然后 set 去重 判断等于0 的加入ts
for i in ts:
'''
>>frozenset((-1, 0, -1))
frozenset({-1, 0})
输入 [-1, 0, 1, 2, -1, -4]
输出{frozenset({2, -1}): (-1, 2, -1), frozenset({0, 1, -1}): (-1, 0, 1)}
'''
bs.update({frozenset(i): i}) if frozenset(i) not in list(bs.keys()) else 0 # 将字典的key作为 frozenset存储
return list(bs.values())
def fourSum_3(self, nums, target):
'''
递归思路
这个其实修改 一下flag的值 就变成n数之和了
'''
def Sum(inp, target, flag):
result = []
if flag == 1:
if target in inp:
return [[target]]
else:
return
else:
for i in range(len(inp)):
if i != 0 and inp[i] == inp[i - 1]:
continue
temp = Sum(inp[i + 1:], target - inp[i], flag - 1)
if temp:
for item in temp:
item.append(inp[i])
result.append(item)
return result
nums.sort()
return Sum(nums, target, 4)
def fourSum_4(self, nums: List[int], target: int) -> List[List[int]]:
'''
速度最快的算法 秒杀前面的所有 击败99%的python用户
'''
result = []
if not nums or len(nums) < 4:
return []
nums.sort()
# 数组长度
length = len(nums)
# 定义4个指针k,i,j,h k从0开始遍历,i从k+1开始遍历,留下j和h,j指向i+1,h指向数组最大值
for k in range(length - 3):
# 当k的值与前面的值相等时忽略
if k > 0 and nums[k] == nums[k - 1]:
continue
# 获取当前最小值,如果最小值比目标值大,说明后面越来越大的值根本没戏
min1 = nums[k] + nums[k + 1] + nums[k + 2] + nums[k + 3]
if min1 > target:
break
# 获取当前最大值,如果最大值比目标值小,说明后面越来越小的值根本没戏,忽略
max1 = nums[k] + nums[length - 1] + nums[length - 2] + nums[length - 3]
if max1 < target:
continue
for i in range(k + 1, length - 2):
if i > k + 1 and nums[i] == nums[i - 1]:
continue
j = i + 1
h = length - 1
min2 = nums[k] + nums[i] + nums[j] + nums[j + 1]
if min2 > target:
continue
max2 = nums[k] + nums[i] + nums[h] + nums[h - 1]
if max2 < target:
continue
# 开始j指针和h指针的表演,计算当前和,如果等于目标值,j++并去重,h--并去重,当当前和大于目标值时h--,当当前和小于目标值时j++
while j < h:
curr = nums[k] + nums[i] + nums[j] + nums[h]
if curr == target:
result.append([nums[k], nums[i], nums[j], nums[h]])
j += 1
while j < h and nums[j] == nums[j - 1]:
j += 1
h -= 1
while j < h and i < h and nums[h] == nums[h + 1]:
h -= 1
elif curr > target:
h -= 1
elif curr < target:
j += 1
return result
print(Solution().fourSum_3([1, 0, -1, 0, -2, 2],0))