四个数之和 & 任意个数的和 转博主下一篇博客链接
一、 题目要求
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
二、 解题思路与python实现
2.1 暴力解法(时间复杂度O(n3))
对于leetcode中任何一道题目,在没有思路的情况下都可以尝试一下暴力解法,虽然时间复杂度会很高, 但是也不妨是一种解题思路。并且在你为暴力解法编写代码的时候说不定就有了新的优化解法思路。
在这道题目里,我们不难想到三重循环遍历这个数组,对于每个组合验证一下是否符合sum==0
这个条件, 如果符合那么就添加到结果数组里,这里需要注意组合存在重复的情况。对于暴力解法这里就不详细解读了,相信大家都看得明白。
python代码实现:
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
from collections import Counter
k = []
result = []
for i, a in enumerate(nums):
for j, b in enumerate(nums[i + 1:]):
for _, c in enumerate(nums[j + i + 2:]):
if a + b + c == 0 and Counter([a, b, c]) not in k:
k.append(Counter([a, b, c]))
for i in k:
result.append(list(i.elements()))
return result
2.2 对撞指针 (时间复杂度O(n2))
相信大家踩过leetcode第一题 两个数的和
的坑,并且对它有了很好的理解(具体解题思路请参考链接,这里不再累述)。当看到这一题时,肯定会想到两个数的和的解题思路,其实这样是对的。
这里对于三元组,我们可以先遍历一次数组,这样就相当于已知了sum和其中一个数, 那么另外两个数的和就确定了,此时对于另外两个数的求和是不是就和两个数的和
一样了呢?所以,这里我们就可以用两个数的和
的方法使用双指针求解了,当然你也可以使用其他你喜欢的算法去求解。
当然这里对于两个数的和,我们使用双指针首先就需要求这个数组排序。nums.sort()
具体python实现:
def threeSum(self, nums):
res = []
nums.sort()
for i in xrange(len(nums)-2):
if nums[i] > 0: break # sum== 0 ,三元组中必然有一个小于等于0 的数 ,如果最小值>0 那么可以跳出循环了
if i > 0 and nums[i] == nums[i-1]: #*排序后相邻两数如果相等,则跳出当前循环继续下一次循环相同的数只需要计算一次
continue
l, r = i+1, len(nums)-1
while l < r:
s = nums[i] + nums[l] + nums[r]
if s < 0:
l +=1
elif s > 0:
r -= 1
else:
res.append((nums[i], nums[l], nums[r])) # 把结果加入数组中
while l < r and nums[l] == nums[l+1]: # 判断相邻元素是否相等,有的话跳过
l += 1
while l < r and nums[r] == nums[r-1]:
r -= 1
l += 1; r -= 1 # 没有相等则j+1,k-1,缩小范围
return res
耗时对比:
1.暴力法 347.76ms
2.优化方案 2.64ms
话不多说,感受下这个天壤之别。