【问题标题】:Finding first pair of numbers in array that sum to value在数组中找到第一对总和为值的数字
【发布时间】:2020-02-22 12:07:09
【问题描述】:

我正在尝试解决以下 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]]

代码似乎产生了正确的结果,但是输入可以由最多包含 10 000 000 个元素的数组组成,因此对于大输入,执行超时。我需要帮助优化/修改代码,以便它可以处理足够大的数组。

【问题讨论】:

  • 我是否遗漏了什么您在第 11 行有语法错误吗?我认为应该改为elif x in m.keys() and x not in dup.keys()
  • @Pame 回答了你的问题

标签: python optimization memoization


【解决方案1】:

不幸的是,这个答案仍然超时,即使它应该在 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

【讨论】:

    【解决方案2】:

    您的代码对于大型列表测试用例效率低下,因此会出现超时错误。相反,您可以这样做:

    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 值之一产生指定总和的值。 欲了解更多信息,请访问:Referance link

    【讨论】:

    • 我测试了它,它运行良好。但是,如果列表中有 10 000 000 个元素,并且没有一对等于 sum 的值,如何不超时?
    【解决方案3】:

    也许这个代码:

    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]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-07
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      相关资源
      最近更新 更多