【问题标题】:Recursive Maximum Subsequence Sum With No Three Consective Elements没有三个连续元素的递归最大子序列和
【发布时间】:2017-08-16 16:54:31
【问题描述】:

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

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

一些示例输入和输出:

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));
}

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

【问题讨论】:

  • 我可以指出的一个错误是您的代码不会考虑序列中的替代元素。这意味着如果最佳选择是选择替代元素,那么这将不起作用。因此,您可能想尝试基于最长递增子序列的递归实现行的另一种递归方法。

标签: algorithm recursion


【解决方案1】:


问题是在没有三个连续元素的情况下获得最大值。

您正在做的是,一次取 3 个元素,从中选择两个具有最大总和的元素,然后添加它们等等。


举个例子:-

Input : {A, B, C, D, E, F}

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

现在,考虑 {A, B, C}
假设, (B + C) &gt; (A + B) and (B + C) &gt; (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,这是你的实际输出。


提示:尝试将未添加的元素索引从一种递归状态传递到另一种状态。如果仍然卡住,请发表评论,我将编写类似的代码:)

【讨论】:

    【解决方案2】:

    问题

    withoutSecondwithoutFirst 有一些错误。为了简单起见,我们假设index &gt;= 3。看withoutSecond

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

    它选择index-1index-3。因此,如果我们在helper(nums, index - 3) 中选择index-4,那么我们不能选择index-5,但它包含在函数withoutThird 中的helper(nums, index - 3) 中。这将产生比预期更大的结果。


    算法

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

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

    1. 如果选择a[n]f(a, n) -&gt; f(a, n-1)
    2. 如果选择a[n] && 选择a[n-1]: f(a, n) -&gt; f(a, n-3) + a[n] + a[n-1]
    3. 如果选择a[n] && 选择a[n-1]: f(a, n) -&gt; f(a, n-2) + a[n]

    好的,这就是全部 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;
    }
    

    【讨论】:

    • 谢谢,我现在理解我的代码的问题了。我明天会测试一下,然后返回结果。
    • 第二种情况不应该是f(a, n) -> f(a, n-3) + a[n] + a[n-1]
    • @marvel308 是的。对不起我的错字。非常感谢!
    猜你喜欢
    • 2015-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    • 1970-01-01
    • 2018-05-22
    • 2011-05-28
    • 2014-10-31
    相关资源
    最近更新 更多