我正在研究程序的一部分,其中我试图输入数字列表并返回3个数字的所有组,这些组的总和为0,而没有对每个数字进行两次或三次计数。这是我要去的地方:
def threeSumZero2(array):
sums = []
apnd=[sorted([x,y,z]) for x in array for y in array for z in array if x+y+z==0]
for sets in apnd:
if sets not in sums:
sums.append(sets)
return sums
我可以在第三行中添加任何代码以确保不返回[0,0,0]作为答案。
这是我的测试清单:
[-1,0,1,2,-1,4]
谢谢
*编辑:对于重复的输入值,我应该进行澄清:此测试列表的预期结果是:
[[-1,-1,2],[-1,0,1]]
答案 0 :(得分:3)
您想要组合而不替换,这是itertools
提供的。然后可以将您的sums
设为一组,以删除有关订购的重复项。
from itertools import combinations
def threeSumZero2(array):
sums = set()
for comb in combinations(array, 3):
if sum(comb) == 0:
sums.add(tuple(sorted(comb)))
return sums
print(threeSumZero2([-1,0,1,2,-1,4]))
{(-1, -1, 2), (-1, 0, 1)}
此解决方案也可以使用集合理解来更简洁地编写。
def threeSumZero2(nums):
return {tuple(sorted(comb)) for comb in combinations(nums, 3) if sum(comb) == 0}
尽管,上述算法需要遍历三项的所有组合,这使其成为 O(n 3 )。
用于这种 n-sum 问题的一般策略是遍历 n-1 组合并对它们的和进行哈希处理,从而可以针对数字有效地对其进行测试在列表中。
算法复杂度下降了一个数量级,使其为 O(n 2 )
from itertools import combinations
def threeSumZero2(nums, r=3):
two_sums = {}
for (i_x, x), (i_y, y) in combinations(enumerate(nums), r - 1):
two_sums.setdefault(x + y, []).append((i_x, i_y))
sums = set()
for i, n in enumerate(nums):
if -n in two_sums:
sums |= {tuple(sorted([nums[idx[0]], nums[idx[1]], n]))
for idx in two_sums[-n] if i not in idx}
return sums
print(threeSumZero2([-1,0,1,2,-1,4]))
{(-1, -1, 2), (-1, 0, 1)}
答案 1 :(得分:0)
您可以使用itertools
进行此操作(请参见Oliver的答案),但是您也可以通过三个嵌套的for循环来获得结果:
def threeSumZero2(lst):
groups = []
for i in range(len(lst)-2):
for j in range(i + 1, len(lst)-1):
for k in range(j + 1, len(lst)):
if lst[i] + lst[j] + lst[k] == 0:
groups.append((lst[i], lst[j], lst[k]))
return groups
和您的测试:
>>> threeSumZero2([-1, 0, 1, 2, -1, 4])
[(-1, 0, 1), (-1, 2, -1), (0, 1, -1)]
哦,还有list
!= array
!