递归最大子数组未返回正确值

Posted

技术标签:

【中文标题】递归最大子数组未返回正确值【英文标题】:Recursive Maximum Subarray not returning correct value 【发布时间】:2021-06-03 11:40:51 【问题描述】:

我正在尝试解决这个问题,给我一个数组,我应该找到最大的差异,即较大的数字在较小的数字之后。例如,如果我有数组:

[100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97]

那么输出应该是(7, 11, 43),其中7 是起始索引(值63),11 是结束索引(值106),43 是差值/利润。

但是,我得到的输出是(0, 16, 1607)

有几个类似问题的线程,但不幸的是我需要非常密切地关注下面的伪代码,所以我找不到有用的东西。

这是我到目前为止的代码。不太确定为什么它给了我错误的输出。请注意,伪代码是基于 1 个索引的,即它从索引 1 而不是 0 开始。

def find_max_crossing_subarray(A, low, mid, high):
    max_left = low
    max_right = high
    left_sum = -math.inf
    sum = 0
    for i in reversed(range(low, mid)):
        sum = sum + A[i]
        if sum > left_sum:
            left_sum = sum
            max_left = i

    right_sum = -math.inf
    sum = 0
    for j in range(mid, high):
        sum = sum + A[j]
        if sum > right_sum:
            right_sum = sum
            max_right = j
    return (max_left, max_right, left_sum + right_sum)


def find_maximum_subarray(A, low, high):
    if low + 1 == high:
        return (low, high, A[low])
    else:
        mid = (low + high) // 2
        (left_low, left_high, left_sum) = find_maximum_subarray(A, low, mid)
        (right_low, right_high, right_sum) = find_maximum_subarray(A, mid, high)
        (cross_low, cross_high, cross_sum) = find_max_crossing_subarray(A, low, mid, high)
        if left_sum >= right_sum and left_sum >= cross_sum:
            return (left_low, left_high, left_sum)
        elif right_sum >= left_sum and right_sum >= cross_sum:
            return (right_low, right_high, right_sum)
        else:
            return (cross_low, cross_high, cross_sum)

bf = find_maximum_subarray(array, 0, len(array))
print(bf)

【问题讨论】:

看起来只是返回整个数组的总和 值 106 在索引 11 处。 你贴的伪代码是针对最大子数组和问题的,与问题中的问题完全无关。 您发送的数组长度为高。这没有任何意义。 @user3386109 抱歉,我修好了。这是我提供的伪代码,所以我不确定。我也添加了问题描述。 【参考方案1】:

这样做不是更容易吗?

def min_max_diff(x):
   def process(x):
       y = sorted(x)
       min = y[0]
       max = sorted(x[x.index(min):])[-1]
       return min, max
    while x:
        min, max = process(x)
        if max <= min:
            x.remove(min)
            min, max = process(x)
        else:
            break
    return min, max, max-min

x = [100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97]
result = min_max_diff(x)
print(result)

【讨论】:

如果数组的最小元素是数组的最后一个元素,则肯定不起作用。 如果元素按从大到小的顺序排列,则没有任何效果 示例:[2,3,1] 已更新以支持此条件 @eatmeimadanish 也许,但如前所述,我必须尽可能地遵循伪代码。是的,我知道这很糟糕..【参考方案2】:

这个问题可以通过对给定数组进行一次遍历来解决,并且您不需要为这个问题计算最大子数组。可能问题陈述和最大子数组是两个不同的问题。

明确提到,您只能购买一只股票并在以后出售。所以,直觉是:

我们总是尽量降低购买价格 对于每一个可能的购买价格,我们都会尝试通过以更高的未来价格出售来最大化利润。

下面的 C++ 代码解决了这个问题:

    int maxProfit(vector<int>& prices) 
        int sz = prices.size();
        if(sz < 2) return 0;
        int mxProfit = -INT_MAX, minPrice = prices[0];
        
        for(int i=0; i<sz; i+=1) 
            mxProfit = max(mxProfit, prices[i] - minPrice);
            minPrice = min(minPrice, prices[i]);
        
        
        return mxProfit;
    

【讨论】:

以上是关于递归最大子数组未返回正确值的主要内容,如果未能解决你的问题,请参考以下文章

使用 D&C/递归的最大子数组

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

每日一题分隔数组以得到最大和

返回整数数组最大子数组之和

分治算法解最大子序列和问题

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