题目:
给定一个包含 n 个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
代码:
class Solution:
def threeSum(self, alist):
resultlist = []
numsset = set()
alist.sort()
target = 0
for x in alist:
numsset.add(x)
for i, j in enumerate(alist[:-2]):
used_nums_set = set()
if j > target/3:
break
elif i > 0 and j == alist[i-1]:
continue
for l, k in enumerate(alist[i+1:-1]):
if k > (target-j)/2:
break
elif l > 0 and k == alist[l+i]:
continue
if alist[l+i+1:].count(k) < 2:
used_nums_set.add(k)
if -(j+k) in numsset and -(j+k) not in used_nums_set:
used_nums_set.add(-(j+k))
resultlist.append([j, k, -(j+k)])
numsset.remove(j)
return resultlist
结果:
311 / 313 个通过测试用例,在312测试用例时超时,该测试用例输入值数量为3000,在本地执行时间为89秒,确实是慢点,留个思路吧
说明:
1.代码功能实现上本身没有问题,在312用例的大量值的情况下超时,由于时间复杂度是O(N平方)的,空间复杂度是O(N)得,比较耗时的部分为列表排序及嵌套循环
2.使用set替代了第三重嵌套循环
3.排序后,列表是从小到大的顺序,由于题目是a+b+c=target,即a+b+c=0,所以a的最大值为target/3,超出部分就不用找了,所以break,对于相同的a值,由于首次循环已经取得了所有可能的值,故只循环一次,多余的跳过,以上操作用于节约一部分时间
4.在固定a值后,循环b值,此时b的最大值为(target - a)/2,操作同a.
5.初始化两个set,一个用于存放列表中所有的值(numsset),另一个(used_nums_set)初始为空但每次循环b值时,存放找到的结果c值,而在a值的一重循环完成后,将a值从 numsset删除,以上操作均以去重为目的
6.固定a值后,b连续出现次数小于2时,则在a的单次循环不能重复使用,判断c值前,需将其提前加入(used_nums_set),否则会出现错误解