【问题标题】:Finding Maximum non-negative Subarray in python在python中查找最大非负子数组
【发布时间】:2019-11-23 07:22:34
【问题描述】:

我试图从给定的子数组中找到包含最大和元素的子数组,而不是任何其他子数组。

下面的函数有参数作为输入a,需要返回输出。可以有多个子数组,因为它们的最大和可以相等。代码似乎没有按预期工作。

def max_sum_subarray(a):
        N, sub_sum, max_sum, subArrays = len(a), 0, 0, {}
        p,q=0,0    #starting and ending indices of a max sub arr

        for i in range(N):
            q=i
            sub_sum+=a[i]

            if(a[i]<0):
                q-=1
                if(sub_sum>=max_sum):
                    if(sub_sum>max_sum):
                        subArrays.clear()
                        subArrays[sub_sum]=[(p,q)]
                    else:
                        subArrays[sub_sum].append((p,q))

                sub_sum=0
                p=i+1

        if(sub_sum>=max_sum):
            if(sub_sum>max_sum):
                subArrays.clear()
                subArrays[sub_sum]=[(p,q)]
            else:
                subArrays[sub_sum].append((p,q))
        return(subArrays[p:q+1])


当我试图运行输入时

a=[ 1, 2, 5, -7, 2, 5 ]

预期的输出是[1, 2, 5],但它却给出了[2, 5]。任何人都可以在python中发布解决方案吗?

【问题讨论】:

  • 介意解释一下你实现的算法吗?
  • subArrays 是一个字典,在运行您的代码时,我在 return 行上得到 TypeError: unhashable type: 'slice'...
  • 方法是,从第一个索引开始,不断的相加,直到找到一个负元素,从现在开始从零开始相加,同时也保持最大的和。在这里,我创建了一个字典更新键,作为迄今为止的最大总和和迄今为止所需的子数组的开始和结束索引。

标签: python sub-array


【解决方案1】:

您似乎使这变得比必要的更难。您可以只跟踪看到的最大数组和您正在推进的当前数组——您真的不需要关心其他任何事情。当你击中负数(或数组的末尾)时,决定当前是否应该是新的最大值:

def maxSub(a):
    max_so_far = []
    max_sum = 0
    cur = []
    for n in a:
        if n >= 0:
            cur.append(n)
        else:
            cur_sum = sum(cur)
            if cur_sum > max_sum:
                max_sum = cur_sum
                max_so_far = cur
            cur = []

    return max([max_so_far, cur], key = sum)


a=[ 1, 2, 5, -7, 2, 5 ]

maxSub(a)
# [1, 2, 5]

当然itertools.groupby 使它成为单行:

from itertools import groupby

a=[ 1, 2, 5, -7, 2, 5 ]
max([list(g) for k,g in groupby(a, key=lambda x: x>0) if k == True], key=sum)

【讨论】:

  • 我喜欢groupby 的方法。另外你不需要cur 列表,只要记住第一个正索引并转到cur_sum = sum(a[firstPositive:n]),性能实际上会更快。
  • 是的,这是一个很好的提示@RadosławCybulski — 谢谢。永远不知道如何在这里平衡概念的清晰性和答案的效率。
  • 这里也一样,对我来说显而易见的事情在我输入后似乎并不那么明显。这实际上是我喜欢回答 SO 的原因,因为它迫使我重新思考我在读者背景下写的所有内容。
  • 这将只接受一些 TC 的形式。对于 TC [ 0, 0, -1, 0] 预期 op 是 0 0 并且它只给出 0 所以为此使用滑动窗口概念。
  • @ShantanuGupta 是[0, 0] 的总和大于[0] 的总和吗?为什么一个优先于另一个?
【解决方案2】:

适用于以下情况:

注意 1:如果有平局,则比较段的长度和 返回具有最大长度的段

注意 2:如果仍有平局,则返回具有最小值的段 起始索引

这是我在 python 中的工作代码:

def check(max_arr,curr):
    if sum(curr) > sum(max_arr):
        max_arr = curr
    elif sum(curr) == sum(max_arr):
        if len(curr) > len(max_arr):
            max_arr = curr
        elif len(curr) == len(max_arr):
            if max_arr and (curr[0] > max_arr[0]):
                max_arr = curr
    return max_arr

def maxset(A):
    curr = []
    max_arr = []
    for i in A:
        if i >= 0:
            curr.append(i)
        else:
            max_arr = check(max_arr,curr)
            curr = []
    max_arr = check(max_arr,curr)                    
    return max_arr

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-14
    • 2021-01-15
    • 2016-05-25
    • 2020-08-30
    • 1970-01-01
    • 2013-09-13
    • 2018-05-23
    • 2021-11-29
    相关资源
    最近更新 更多