3SUM为特定值

时间:2018-06-28 10:10:06

标签: python algorithm subset-sum

我目前有一个解决方案,但仍然慢了约300%。问题是从给定列表中找到三个数字的子集,它们的总和为n。

goal = int(input().split()[1]) #The desired sum
numbers = list(map(int, input().split())) #User-inputted numbers

myDict = {} #Created so we can quickly check if a number is present in the list

for i in numbers: #The amount of each number is stored in the dict, eg. 439797: 2
    if i in myDict:
        myDict[i] += 1
    else:
        myDict[i] = 1


numbers = sorted(numbers)


for start in range(0, len(numbers)):
    for end in range(1, len(numbers)):
        myDict[numbers[start]] -= 1 
        myDict[numbers[end]] -= 1 
        #This is done so that the same number isn't used twice
        if goal-numbers[start]-numbers[end] in myDict:
            if myDict[goal-numbers[start]-numbers[end]] > 0:
                print(goal-numbers[start]-numbers[end], numbers[start], numbers[end])
                quit()
        myDict[numbers[start]] += 1
        myDict[numbers[end]] += 1

2 个答案:

答案 0 :(得分:1)

您要在内循环中对字典进行六次索引,这是完全不必要的,并且可能占用了您大量的运行时间。您可以只使用一个索引操作,而无需对字典进行任何修改:

for i in range(0, len(numbers)):
    m = numbers[i]
    for j in range(i + 1, len(numbers)):
        n = numbers[j]
        if n != m:
            k = goal - m - n
            if k != m and k != n and k in myDict:
                # accept triple (m, n, k)

此外,正如评论中已经建议的那样,对输入进行排序没有任何意义。

更新:同样,从注释中,您的内循环从1开始。这大约使您的运行时间加倍。

更新2 :另外,由于不再需要字典中的计数,因此现在可以将其设置为字典(但不确定它是否会以任何有意义的方式影响性能。)

更新3 :添加了对n != m的检查。

答案 1 :(得分:1)

我完全同意shinobi,但是如果您需要快速计算这些任务,那么C ++是可行的方法。代码如下:

for (int i = 0, i < len(numbers); i++) {
    int m = numbers[i];
    for (int j = i + 1, j < len(numbers); j++) {
        int n = numbers[j];
        if (n != m) {
            int k = goal - m - n;
            if (k != m && k != n && myDict[k]) {
                doSomething();
        }
    }
}