我最近有一个测试问题要求列出并计算给定列表中的所有对和,然后返回总和等于给定目标值的次数。
我编写了代码,并认为它当时是正确的,但它看起来像是两次对。我想弄清楚一种方法,以确保我不重复对数。
我显然没有正确地得到面试问题。我的想法是存储哪些指数已经汇总并跳过它们,如果有的话?
*对不必连续
myList = [1,4,6,7,8]
def getSums(myList,target):
l_ = len(myList)
sums = []
for i in range(l_):
for j in range(l_):
if i==j:
continue
else:
sums.append((myList[i],myList[j],myList[i]+myList[j]))
return [x for x in sums if x[2]==target]
print getSums(myList,5)
答案 0 :(得分:1)
在这里,我们模拟了itertools.combinations
的淡化版本。
<强>代码强>
def combinations(iterable):
"""Return r=2 combinations of an iterable."""
# Inherently, r=2 (pairs) by using two loops
pool = []
for idx_i, i in enumerate(iterable):
for idx_j, j in enumerate(iterable):
if (idx_i != idx_j) and ((j,i) not in pool):
pool.append((i, j))
return pool
def get_sums(iterable, target):
"""Return the tally of summed paired equal to the target value."""
results = [sum(i) for i in combinations(lst)]
return len([i for i in results if i == 5])
get_sums([1, 4, 6, 7, 8], 5)
# 1
<强>详情
让我们将问题分成3个步骤:
idx_i != idx_j
(lst[0], lst[1])
与(lst[1], lst[0])
选项强>
如果允许, itertools
肯定更好:
import itertools as it
lst, target = [1, 4, 6, 7, 8], 5
results = [sum(i) for i in list(it.combinations(lst, 2))]
len([i for i in results if i == target])
# 1
实际上,我从itertools
解决方案开始并向后工作,清除基本逻辑,然后替换模块依赖。也许这是一种可以用来“重新发明轮子”的策略。
答案 1 :(得分:0)
我会使用类似的东西:
from collections import Counter
myList = [1,4,6,7,8]
c = Counter(myList)
sum([k for k,v in c.items() if v == 2])
修改了第一个例子(未经测试,只是逻辑示例):
myList = [1,4,6,7,8]
def getSums(myList,target):
l_ = len(myList)
sums = []
for i in range(len(myList)):
for item in myList[i:]:
sums.append((myList[i],item,myList[i]+item))
return [x for x in sums if x[2]==target]
print getSums(myList,5)
答案 2 :(得分:0)
作为一个面试问题,这是一个算法问题,所以这就是解决方案,你会发现它是许多算法书中的一个非常基本的问题。
myList = [1, 4, 6, 7, 8]
def getSums(myList, target):
lst = sorted(myList)
i = 0
j = len(lst) - 1
while i <= j:
tmp = lst[i] + lst[j]
if tmp > target:
j -= 1
continue
elif tmp < target:
j += 1
continue
else:
return [lst[i], lst[j]]
raise Exception('No available pair found')
print(getSums(myList, 5))
答案 3 :(得分:0)
我认为它是重复计算的,因为你要经历两次列表,一次是通过索引i,一次是通过索引j。
我得到以下代码以产生正确的结果。我添加了值3,以便我可以看到它是否会发现总和为10的所有对。
myList = [1,3,4,6,7,8]
target = 10
def getSums(myList,target):
l_ = len(myList)
sums = []
for i in range(l_):
for j in range(l_):
if i!=j:
if (myList[i] + myList[j]) == target:
if myList[i] not in sums:
sums.append(myList[i])
sums.append(myList[j])
print sums
getSums(myList, target)
答案 4 :(得分:0)
你确定你必须计算所有对的总和吗?这是非常低效的,不是必需的。使用集合,您可以在一次通过中解决此问题,而无需外部库。
算法以这种方式工作:
target - element
。
element
已经看到了。以下是代码:
myList = [1,4,6,0,2,7,8,3,5]
def getSums(myList,target):
already_seen = set()
pairs = []
for x in myList:
if (target - x) in already_seen:
pairs.append((x, target - x))
already_seen.add(x)
return pairs
print(getSums(myList,5))
# [(4, 1), (3, 2), (5, 0)]
此解决方案应适用于具有唯一元素的任何列表。该列表不需要排序。与其他解决方案的O(n)
相比,复杂度为O(n**2)
。
如果元素不是唯一的,您可以使用Counter
代替set
:
myList = [1,4,6,0,2,7,8,3,5]
from collections import Counter
def getSums(myList,target):
already_seen = Counter()
pairs = []
for x in myList:
for _ in range(already_seen[target - x]):
pairs.append((x, target - x))
already_seen[x] += 1
return pairs
print(getSums(myList,5))
# [(4, 1), (3, 2), (5, 0)]
print(getSums([2, 2, 2],4))
# [(2, 2), (2, 2), (2, 2)]
最后的结果与其他答案一致。