【问题标题】:Recursive, Divide-and-conquer algorithm for longest non-decreaseing array of numbers最长非递减数字数组的递归分治算法
【发布时间】:2011-12-04 22:14:06
【问题描述】:

我遇到了一些严重的问题。我需要一个“分而治之”的递归算法,它告诉我最长的非递减数字数组的长度。就个人而言,我会选择使用我在仔细阅读问题之前编写的这段代码。

 int bestIndex = 0;
    int bestLength = 0;
    int curIndex = 0;
    int curLength = 1;

    for (int i = 1; i < a.length; i ++){
        if (a[i] >= a[i-1]){
            curLength ++;
        }else {
            curLength = 1;
            curIndex = i;
        }
        if (curLength > bestLength){
            bestIndex = curIndex;
            bestLength = curLength;
        }
    }
    return bestLength;

问题是任务要求我使用分而治之,我想不出一种方法来做到这一点。

例如“4 2 3 3 1 2 4 5 9 2” 由于“1 2 4 5 9”,它将返回“5”

非常感谢任何帮助。

谢谢

【问题讨论】:

  • 遍历列表,选择“分裂点”作为减少的地方。但是,除非您在中间附近选择一个分割点,否则这不会真正“分割”。我会从中间开始,然后向外迭代。循环 i= m(中间),然后是 m-1、m+1、m-2、m+2 等,直到 i 和 i+1 之间减少。然后在那里将数组切成两半并在每一半上递归。当不存在减数时,返回序列的长度。

标签: algorithm


【解决方案1】:

您确定子数组需要由连续元素组成吗?对于子序列,这个问题变得更加有趣......

无论如何,如果您需要分而治之的算法,请尝试遵循基本蓝图:

function f(array) =
    if array is empty or constant size or something like that
        handle base case
    else
        result1 <- f(first half of the array)
        result2 <- f(second half of the array)
        return some_way_to_combine(result1, result2)

当然,您需要正确选择 f 应该返回的值来帮助您。您将需要处理增加的子数组在其中一个半内的情况和跨越边界的情况。

【讨论】:

    【解决方案2】:

    另一个答案是一个很好的通用答案。

    但是,我建议关键是要知道在组合结果时需要能够回答哪些问题。如果结果 1 代表数组 [i,j] 而结果 2 代表 [j+1,k] 那么这些是您需要能够回答的问题:

    • 以 j 结尾的最长非递减序列是什么?
    • 从 j+1 开始的最长非递减序列是什么?
    • 到目前为止我见过的最大长度序列是多少(包括以 j 结尾并从 j+1 开始的序列)?

    如果您假设您已经可以为 result1 和 result2 回答这些问题,那么您应该能够为您的组合结果 [i, k] 定义答案(即从 i 开始的最长序列和从 k 开始的最长序列,如以及迄今为止你见过的最长的,包括这两个)。

    【讨论】:

      猜你喜欢
      • 2021-05-11
      • 2016-06-28
      • 2016-05-01
      • 2011-12-06
      • 2014-04-21
      • 1970-01-01
      • 2019-08-08
      • 2017-08-19
      • 1970-01-01
      相关资源
      最近更新 更多