没有三个有效元素的递归最大子序列和

时间:2017-08-16 06:05:00

标签: algorithm recursion

我试图使用递归来解决最大化子序列和的方法,使得没有三个元素是连续的。

有一种方法可以通过动态编程实现这一点,但我想首先使用递归来构建它。

一些示例输入和输出:

Input:{1, 2, 3}
Output: 5

Input:{100, 1000, 100, 1000, 1}
Output: 2101

Input:{1, 2, 3, 4, 5, 6, 7, 8}
Output: 27

除了第二个{100,1000,100,1000,1}之外,我能够得到大部分正确的结果。

我的解决方案:

int maxSubsequenceSum(vector<int> nums)
{
    return helper(nums, nums.size());
}

int helper(vector<int>& nums, int index)
{
    if (index <= 0) return 0;

    int withoutThird = helper(nums, index - 3) + nums[index - 1] + nums[index - 2];
    int withoutSecond = helper(nums, index - 3) + (index - 1 < 0 ? 0 : nums[index - 1]) + (index - 3 < 0 ? 0 : nums[index - 3]);
    int withoutFirst = helper(nums, index - 3) + (index - 2 < 0 ? 0 : nums[index - 2]) + (index - 3 < 0 ? 0 : nums[index - 3]);
    return max(withoutThird, max(withoutSecond, withoutFirst));
}

单独地,三个 withoutThird withoutSecond withoutFirst 仅在递归排列时才会给出正确的结果。为什么它会失败,这是一种正确的递归方法吗?

2 个答案:

答案 0 :(得分:2)


问题是使用没有三个连续元素来获得最大值。

您正在做的是,一次取3个元素,从中选择两个元素,添加它们等等。  

<小时/> 举一个例子: -
Input : {A, B, C, D, E, F}

当你的递归从右到左。
假设,考虑,{D,E,F}
(D + E) > (E + F) and (D + E) > (D + F)
您的代码将从最后3个元素中选择{D, E}

现在,考虑,{A,B,C}假设, (B + C) > (A + B) and (B + C) > (A + C)
您的代码将从前3个元素中选择{B, C}

总选定元素= {B,C,D,E}。
注意到什么?
您最终添加了四个连续元素。

一个简短的例子:{100,1000,100,1000,1} 2个窗口:[0,1]和[2,4]
从[2,4]中选择{100,1000} 并从[0,1]中选择{100,1000} 添加了四个连续元素  得到:2200,这是你的实际输出。

<小时/> 提示:尝试传递你没有从一种递归状态添加到另一种状态的元素索引。如果仍然卡住,评论,我会写一个类似的代码:)

答案 1 :(得分:1)

问题

withoutSecondwithoutFirst有一些错误。为简化起见,我们假设index >= 3。看看withoutSecond

withoutSecond = helper(nums, index - 3) + nums[index - 1] + nums[index - 3]

选择index-1index-3。因此,如果我们在index-4中选择helper(nums, index - 3),则我们无法选择index-5,但它包含在函数withoutThird中的helper(nums, index - 3)中。这会产生更大的结果。

算法

由于条件不允许 3 连续元素。所以我们只需要考虑 2 连续元素来决定是否应该选择另一个元素。

假设f(a, n)计算大小为a的数组n的最大结果。

  1. 如果选择a[n]f(a, n) -> f(a, n-1)
  2. 如果选择a[n]&amp;&amp;选择a[n-1]f(a, n) -> f(a, n-3) + a[n] + a[n-1]
  3. 如果选择a[n]&amp;&amp; 选择a[n-1]f(a, n) -> f(a, n-2) + a[n]
  4. 好的,这就是所有3个案例。

    代码

    有关详细信息,请参阅以下代码

    #include <vector>
    #include <cstdio>
    using namespace std;
    
    // this runs slow
    // but you can use memorized search to speed up the process
    int helper(vector<int>& nums, int index) {
        if (index == 0) return 0;
        if (index == 1) return nums[0];
        if (index == 2) return nums[0] + nums[1];
    
        int without_last_1                 = helper(nums, index-1);
        int with_last_1_and_2              = helper(nums, index-3) + nums[index-1] + nums[index-2];
        int with_last_1_and_without_last_2 = helper(nums, index-2) + nums[index-1];
    
        return max(without_last_1, max(with_last_1_and_2, with_last_1_and_without_last_2));
    }
    
    int maxSubsequenceSum(vector<int> nums) {
        return helper(nums, nums.size());
    }
    
    int main() {
        printf("%d\n", maxSubsequenceSum({1, 2, 3}));
        printf("%d\n", maxSubsequenceSum({100, 1000, 100, 1000, 1}));
        printf("%d\n", maxSubsequenceSum({1, 2, 3, 4, 5, 6, 7, 8}));
        return 0;
    }