最大和子数组 - 返回子数组和总和 - 分而治之

Posted

技术标签:

【中文标题】最大和子数组 - 返回子数组和总和 - 分而治之【英文标题】:Maximum Sum Subarray - Return Subarray and sum - Divide and Conquer 【发布时间】:2017-06-08 11:06:40 【问题描述】:

我需要为使用分治法的最大和子数组算法返回总和和子数组。

我能够在所有测试中正确计算总和。但是,我无法计算出正确的子数组。

class Results:
    max = 0
    maxSubArray = []
    start_index = 0
    stop_index = 0

def divide_and_conquer(arr, left, right):
    res = Results()

    maxLeftBorderSum = 0
    maxRightBorderSum = 0
    leftBorderSum = 0
    rightBorderSum = 0
    center = (left + right)//2

    if left == right:
        if(arr[left]>0):
            res.max = arr[left]
            res.start_index = left
            res.stop_index = right
            res.maxSubArray = arr[left:right]
            return res
        else:
            res.max = 0
            res.start_index = left
            res.stop_index = right
            res.maxSubArray = arr[:]
            return res

    maxLeft = divide_and_conquer(arr, left, center)
    maxRight = divide_and_conquer(arr, center+1, right)

    maxLeftSum = maxLeft.max
    maxRightSum = maxRight.max

    rightstopindex = 0
    leftstartindex = 0

    for i in range(center, left-1, -1):
        leftBorderSum = leftBorderSum + arr[i]
        if leftBorderSum > maxLeftBorderSum:
            maxLeftBorderSum = leftBorderSum
            leftstartindex = i

    for i in range(center+1, right+1):
        rightBorderSum = rightBorderSum + arr[i]
        if rightBorderSum > maxRightBorderSum:
            maxRightBorderSum = rightBorderSum
            rightstopindex = i

    res.max = max(maxLeftBorderSum + maxRightBorderSum, max(maxRightSum, maxLeftSum))

    if res.max == maxLeftBorderSum + maxRightBorderSum:
        res.start_index = leftstartindex
        res.stop_index = rightstopindex
        res.maxSubArray = arr[leftstartindex:rightstopindex]
    elif res.max == maxRightSum:
        res.start_index = maxRight.start_index
        res.stop_index = maxRight.stop_index
        res.maxSubArray = arr[maxRight.start_index:maxLeft.stop_index]
    else:
        res.start_index = maxLeft.start_index
        res.stop_index = maxLeft.stop_index
        res.maxSubArray = arr[maxLeft.start_index:maxLeft.stop_index]

    return res

样本输出

数组:1 4 -9 8 1 3 3 1 -1 -4 -6 2 8 19 -10 -11

正确的子数组:8 1 3 3 1 -1 -4 -6 2 8 19

我的结果:[8, 1, 3, 3, 1, -1, -4, -6, 2, 8]

我的总和(正确):34


数组:2 9 8 6 5 -11 9 -11 7 5 -1 -8 -3 7 -2

正确的子数组:2 9 8 6 5

我的结果:[2, 9, 8, 6]

我的总和(正确):30


数组:10 -11 -1 -9 33 -45 23 24 -1 -7 -8 19

正确的子数组:23 24 -1 -7 -8 19

我的子数组:[10, -11, -1, -9, 33, -45, 23, 24, -1, -7, -8]

我的总和(正确):50


数组:31 -41 59 26 -53 58 97 -93 -23 84

正确的子数组:59 26 -53 58 97

我的子数组:[59, 26, -53, 58]

我的总和(正确):187


数组:3 2 1 1 -8 1 1 2 3

正确的子数组3 2 1 1

我的子数组[3, 2, 1, 1, -8, 1, 1, 2]

我的总和(正确)7


数组:12 99 99 -99 -27 0 0 0 -3 10

正确的子数组:12 99 99

我的子数组[]

我的总和(正确)210


数组:-2 1 -3 4 -1 2 1 -5 4

正确的子数组 4 -1 2 1

我的子数组 [4, -1, 2]

我的总和(正确)6

【问题讨论】:

第二个 for 循环有问题。应该是 rightstopindex = i + 1 数组中有负数时出现问题。 【参考方案1】:

以下变量需要以不同方式初始化。因为它们在上面的代码中被设为零,所以当数组只包含负数时,有时它们在循环中永远不会改变。

maxLeftBorderSum = arr[center]
maxRightBorderSum = arr[center+1]
leftstartindex = center
rightstopindex = center+1

【讨论】:

以上是关于最大和子数组 - 返回子数组和总和 - 分而治之的主要内容,如果未能解决你的问题,请参考以下文章

在 O(nlogn) 时间复杂度中找到总和为 0 的子数组(使用分而治之)?

返回错误输出的最大和子数组

最大子阵列和

最大子数组:分而治之

绪论—最大子列和问题

JavaScript 算法题:从一个数组中找出总和最大的连续子数组