了解递归/如何组合子问题(最大子阵列算法)

时间:2014-04-15 16:24:27

标签: algorithm recursion divide-and-conquer

我在理解分而治之算法时遇到了一些问题。我已经读过,为了成功地应用递归,你需要有一个“信仰的递归跳跃”,你不应该为每一步的细节而烦恼,但我真的不满意只接受递归有效条件得到满足,因为此刻对我来说似乎很神奇,我想知道它为什么会起作用。

所以我给出了以下在伪代码中找到最大子阵列的递归算法:

Find-Maximum-Subarray(A, low, high)
if high == low
    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 + 1, 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)
    else if right-sum >= left-sum and right-sum >= cross-sum
        return (right-low, right-high, right-sum)
    else
        return (cross-low, cross-high, cross-sum)

其中Find-Max-Crossing-Subarray算法由以下伪代码给出:

Find-Maximum-Crossing-Subarray(A, low, mid, high)
left-sum = -INF
sum = 0
for i = mid down to low
    sum = sum + A[i]
    if sum > left-sum
        left-sum = sum
        max-left = i
right-sum = -INF
sum = 0
for j = mid + 1 to high
    sum = sum + A[j]
    if sum > right-sum 
        right-sum = sum
        max-right = j
return (max-left, max-right, left-sum + right-sum)

现在,当我尝试将此算法应用于示例时,我很难理解所有步骤。

数组被“分解”(使用索引,而不实际更改数组本身),直到高等于低。我认为这对应于第一次调用,因此首先为数组左边的所有项调用Find-Maximum-Subarray,直到high == low == 1。然后返回(低,高,A [低]),在这种情况下将是(1,1,A [1])。现在我不明白在调用的剩余部分中如何处理这些值。

此外,我不明白算法实际上如何比较长度的子阵列> 1.任何人都可以向我解释一旦该函数的一个调用已经触底,算法是如何继续的吗?

1 个答案:

答案 0 :(得分:2)

简而言之:
A为长度为n的数组。您想要计算调用A的{​​{1}}的最大子阵列。现在尝试使问题更容易:

  1. 为例。高=低:
    在这种情况下,Array只有1个元素,因此解决方案很简单
  2. 高!=低
    在这种情况下,难以找到解决方案。所以尽量减少问题。如果我们将数组Find-Maximum-Subarray(A, 0, n-1)切割成半长的数组AB1会发生什么。现在只有3个新案例

    a)B2的最大子阵列也是A的子阵列,但不是B1的子阵列 b)B2的最大子阵列也是A的子阵列,但不是B2的子阵列 c)B1的最大子阵列与AB1

    重叠

    因此,您需要分别计算B2B1的最大子阵列,并寻找重叠的解决方案,最后选择最大的解决方案。

  3. 现在的诀窍是,您可以使用B2B1进行同样的操作。

    示例:

    B2