二次复杂度的 4SUM 变化 (Python 3.5)
4SUM variation in quadratic complexity (Python 3.5)
我对 4SUM 问题的变体遇到了一些问题。本质上,我们需要从每个 500 个整数的 4 个元组中选择一个数字,例如 i
、j
、k
、l
,例如 a
、b
、c
、d
,这样 i+j+k+l == 0
。这些整数的范围从 -20000
到 20000
。目前,我相信我的代码的时间复杂度为 O(n3)。根据我的导师的说法,这个时间复杂度可以进一步降低到 O(n2 log n) 或 O (n2)(通过使用哈希表或其他东西)。
不幸的是,如果这种哈希表方法是可行的方法,我不确定如何着手实施它。因此,如果有人能告诉我如何在 Python 3.5 中编写此程序,我将不胜感激。 (PS。请尽量使用尽可能少的嵌套循环,none 是最理想的)。
我在下面附上了我的代码以供参考。如果可以修改我当前的代码以降低其时间复杂度,请同时通知我。
import collections
import itertools
def selection(a, b, c, d):
"""program has 4 main parts,
firstly, triple_sum finds possible 3sums in the list abc
secondly, is_iterable ensures that inputs of tuple length 1 (ie. not iterable) are made iterable
thirdly, main function determines if there exists possible a, b, c in abc that correspond to each d
fourthly, main function checks if only 1 of the 3 integers from triple_sum exist in each array"""
'''use sort O(n log n) to sort input array, then find possible 3sums in O(n^2)'''
def triple_sum(a, res):
a.sort()
positions = collections.defaultdict(set)
for i, n in enumerate(a):
positions[n].add(i)
for (i, ai), (j, aj) in itertools.combinations(enumerate(a), 2):
n = res - ai - aj
if positions[n].difference((i, j)):
return n, ai, aj
'''Ensure that all inputs are iterable'''
def is_iterable(x):
if isinstance(x, collections.Iterable):
return x
else:
return x,
a, b, c, d = is_iterable(a), is_iterable(b), is_iterable(c), is_iterable(d)
abc = a + b + c
abc = [i for i in abc]
'''find value of d which has corresponding a, b, c
and returns appropriate value if conditions are met'''
ans_a, ans_b, ans_c, ans_d = 0, 0, 0, 0
for i in d:
x = 0 - i
j = triple_sum(abc, x)
if j[0] in a and j[1] in b and j[2] in c:
ans_a, ans_b, ans_c, ans_d = j[0], j[1], j[2], i
break
elif j[0] in a and j[2] in b and j[1] in c:
ans_a, ans_b, ans_c, ans_d = j[0], j[2], j[1], i
break
elif j[1] in a and j[0] in b and j[2] in c:
ans_a, ans_b, ans_c, ans_d = j[1], j[0], j[2], i
break
elif j[1] in a and j[2] in b and j[0] in c:
ans_a, ans_b, ans_c, ans_d = j[1], j[2], j[0], i
break
elif j[2] in a and j[0] in b and j[1] in c:
ans_a, ans_b, ans_c, ans_d = j[2], j[0], j[1], i
break
elif j[2] in a and j[1] in b and j[0] in c:
ans_a, ans_b, ans_c, ans_d = j[2], j[1], j[0], i
break
else:
continue
return ans_a, ans_b, ans_c, ans_d
提前致谢:)
PS。如果有人需要更多说明或信息,请告诉我。
理论
遍历所有 (i,j)
对并创建一个以 i+j
为键和 (i,j)
为值的字典
遍历所有 (k,l)
对并创建一个以 -(k+l)
为键和 (k,l)
为值的字典。
遍历第一个字典的键,并检查第二个字典是否也有这个键。在这种情况下,sum((i,j,k,l))
将是 0
。
每个描述的步骤都是 O(n²)
,因此整个算法将是 O(n²)
,其中 n
是元组的大小。
代码
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
c = [9, 10, 11, 12]
d = [13, 14, 15, -24]
def pairs_and_sums(list1, list2):
return {(x + y): (x, y) for x in list1 for y in list2}
first_half = pairs_and_sums(a, b)
second_half = pairs_and_sums(c, d)
for i_plus_j in first_half:
if -i_plus_j in second_half:
i, j = first_half.get(i_plus_j)
k, l = second_half.get(-i_plus_j)
print("Solution found!")
print("sum((%d,%d,%d,%d)) == 0" % (i, j, k, l))
break
else:
print "No solution found"
它输出:
Solution found!
sum((4,8,12,-24)) == 0
我对 4SUM 问题的变体遇到了一些问题。本质上,我们需要从每个 500 个整数的 4 个元组中选择一个数字,例如 i
、j
、k
、l
,例如 a
、b
、c
、d
,这样 i+j+k+l == 0
。这些整数的范围从 -20000
到 20000
。目前,我相信我的代码的时间复杂度为 O(n3)。根据我的导师的说法,这个时间复杂度可以进一步降低到 O(n2 log n) 或 O (n2)(通过使用哈希表或其他东西)。
不幸的是,如果这种哈希表方法是可行的方法,我不确定如何着手实施它。因此,如果有人能告诉我如何在 Python 3.5 中编写此程序,我将不胜感激。 (PS。请尽量使用尽可能少的嵌套循环,none 是最理想的)。
我在下面附上了我的代码以供参考。如果可以修改我当前的代码以降低其时间复杂度,请同时通知我。
import collections
import itertools
def selection(a, b, c, d):
"""program has 4 main parts,
firstly, triple_sum finds possible 3sums in the list abc
secondly, is_iterable ensures that inputs of tuple length 1 (ie. not iterable) are made iterable
thirdly, main function determines if there exists possible a, b, c in abc that correspond to each d
fourthly, main function checks if only 1 of the 3 integers from triple_sum exist in each array"""
'''use sort O(n log n) to sort input array, then find possible 3sums in O(n^2)'''
def triple_sum(a, res):
a.sort()
positions = collections.defaultdict(set)
for i, n in enumerate(a):
positions[n].add(i)
for (i, ai), (j, aj) in itertools.combinations(enumerate(a), 2):
n = res - ai - aj
if positions[n].difference((i, j)):
return n, ai, aj
'''Ensure that all inputs are iterable'''
def is_iterable(x):
if isinstance(x, collections.Iterable):
return x
else:
return x,
a, b, c, d = is_iterable(a), is_iterable(b), is_iterable(c), is_iterable(d)
abc = a + b + c
abc = [i for i in abc]
'''find value of d which has corresponding a, b, c
and returns appropriate value if conditions are met'''
ans_a, ans_b, ans_c, ans_d = 0, 0, 0, 0
for i in d:
x = 0 - i
j = triple_sum(abc, x)
if j[0] in a and j[1] in b and j[2] in c:
ans_a, ans_b, ans_c, ans_d = j[0], j[1], j[2], i
break
elif j[0] in a and j[2] in b and j[1] in c:
ans_a, ans_b, ans_c, ans_d = j[0], j[2], j[1], i
break
elif j[1] in a and j[0] in b and j[2] in c:
ans_a, ans_b, ans_c, ans_d = j[1], j[0], j[2], i
break
elif j[1] in a and j[2] in b and j[0] in c:
ans_a, ans_b, ans_c, ans_d = j[1], j[2], j[0], i
break
elif j[2] in a and j[0] in b and j[1] in c:
ans_a, ans_b, ans_c, ans_d = j[2], j[0], j[1], i
break
elif j[2] in a and j[1] in b and j[0] in c:
ans_a, ans_b, ans_c, ans_d = j[2], j[1], j[0], i
break
else:
continue
return ans_a, ans_b, ans_c, ans_d
提前致谢:)
PS。如果有人需要更多说明或信息,请告诉我。
理论
遍历所有
(i,j)
对并创建一个以i+j
为键和(i,j)
为值的字典遍历所有
(k,l)
对并创建一个以-(k+l)
为键和(k,l)
为值的字典。遍历第一个字典的键,并检查第二个字典是否也有这个键。在这种情况下,
sum((i,j,k,l))
将是0
。
每个描述的步骤都是 O(n²)
,因此整个算法将是 O(n²)
,其中 n
是元组的大小。
代码
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
c = [9, 10, 11, 12]
d = [13, 14, 15, -24]
def pairs_and_sums(list1, list2):
return {(x + y): (x, y) for x in list1 for y in list2}
first_half = pairs_and_sums(a, b)
second_half = pairs_and_sums(c, d)
for i_plus_j in first_half:
if -i_plus_j in second_half:
i, j = first_half.get(i_plus_j)
k, l = second_half.get(-i_plus_j)
print("Solution found!")
print("sum((%d,%d,%d,%d)) == 0" % (i, j, k, l))
break
else:
print "No solution found"
它输出:
Solution found!
sum((4,8,12,-24)) == 0