在数组中找到第一对相加等于给定值的数字。

3
我将尝试解决以下的 Codewars 问题:https://www.codewars.com/kata/sum-of-pairs/train/python 这是我当前在 Python 中的实现:
def sum_pairs(ints, s):
    right = float("inf")

    n = len(ints)
    m = {}
    dup = {}

    for i, x in enumerate(ints):
        if x not in m.keys():
            m[x] = i # Track first index of x using hash map. 
        elif x in m.keys() and x not in dup.keys():
            dup[x] = i

        for x in m.keys():
            if s - x in m.keys():
                if x == s-x and x in dup.keys():
                    j = m[x]
                    k = dup[x]
                else:
                    j = m[x]
                    k = m[s-x]


                comp = max(j,k)
                if comp < right and j!= k:
                    right = comp


    if right > n:
        return None

    return [s - ints[right],ints[right]]

代码似乎能够产生正确的结果,但输入可以包含多达10000000个元素的数组,因此对于大型输入而言,执行时间会超时。我需要优化/修改代码以便能够处理足够大的数组。

2
我是否漏掉了什么?你在第11行有语法错误吗?我认为应该改成elif x in m.keys() and x not in dup.keys() - David Cian
@Pame回答了你的问题。 - Sid
3个回答

3
您的代码在大型列表测试案例中效率低下,因此会导致超时错误。相反,您可以执行以下操作:
def sum_pairs(lst, s):
    seen = set()
    for item in lst:
        if s - item in seen:
            return [s - item, item]
        seen.add(item)

我们将值放入seen,直到我们找到一个值与seen中的某个值产生指定的总和。 详细信息请参阅:参考链接

我已经测试过了,它的表现非常好。但是如果列表中有10,000,000个元素,并且没有一对值等于总和,它如何不超时? - user9231414

1
也许是这段代码:
def sum_pairs(lst, s):
    c = 0
    while c<len(lst)-1:
        if c != len(lst)-1: 
            x= lst[c]
            spam = c+1
            while spam < len(lst):
                nxt= lst[spam]
                if nxt + x== s:
                    return [x, nxt]
                spam += 1
        else:
            return None
        c +=1
lst = [5, 6, 5, 8]
s = 14
print(sum_pairs(lst, s)) 

输出:

[6, 8]

0

很不幸,这个答案仍然超时了,尽管它应该在O(n^3)内运行(因为它被排序所支配,算法的其余部分运行在O(n)内)。我不确定如何获得比这更好的复杂度,但我想我可以提出这个想法。

def sum_pairs(ints, s):
    ints_with_idx = enumerate(ints)

    # Sort the array of ints
    ints_with_idx = sorted(ints_with_idx, key = lambda (idx, num) : num)

    diff = 1000000
    l = 0
    r = len(ints) - 1

    # Indexes of the sum operands in sorted array
    lSum = 0
    rSum = 0

    while l < r:
        # Compute the absolute difference between the current sum and the desired sum
        sum = ints_with_idx[l][1] + ints_with_idx[r][1]
        absDiff = abs(sum - s)
        if absDiff < diff:
            # Update the best difference
            lSum = l
            rSum = r
            diff = absDiff
        elif sum > s:
            # Decrease the large value
            r -= 1
        else:
            # Test to see if the indexes are better (more to the left) for the same difference
            if absDiff == diff:
                rightmostIdx = max(ints_with_idx[l][0], ints_with_idx[r][0])
                if rightmostIdx < max(ints_with_idx[lSum][0], ints_with_idx[rSum][0]):
                    lSum = l
                    rSum = r
            # Increase the small value
            l += 1

    # Retrieve indexes of sum operands
    aSumIdx = ints_with_idx[lSum][0]
    bSumIdx = ints_with_idx[rSum][0]

    # Retrieve values of operands for sum in correct order
    aSum = ints[min(aSumIdx, bSumIdx)]
    bSum = ints[max(aSumIdx, bSumIdx)]

    if aSum + bSum == s:
        return [aSum, bSum]
    else:
        return None

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接