当前位置: 首页 > 知识库问答 >
问题:

具有最大和加约束的最长递增子序列 - 可以跳过允许的元素数

聂风史
2023-03-14

具有最大和(http://www.geeksforgeeks.org/dynamic-programming-set-14-maximum-sum-increasing-subsequence/)的最长递增子序列是一个经典的算法问题,并且网络上存在许多解决方案。但是,我只是遇到了这个问题的变体,不知道如何解决它。

与原始问题相比,现在还为您提供了一个数字m,该数字表示您最多可以从连续子范围中跳过的元素数,以便找到具有最大总和的LIS。例如,使用以下数组,

[1,200,300,3,4,5,6]

LIS 为 1,3,4,5,6,最大和为 19。但是,如果 m 为 1,则意味着在连续子范围内最多可以跳过一个元素以查找 LIS。因此,上述解决方案是不正确的,因为在 1 和 3 之间,跳过了两个元素(在本例中为 200,300)。新解决方案应为 3,4,5,6,因为在连续子范围内不会跳过任何元素。问题是找到具有最大和的LIS,并在给出数组和数字m时返回子序列(而不是子序列的总和或长度)。我已经坚持这个问题好几天了,所以任何帮助都是值得赞赏的。

编辑:O(n^2)解决方案现在已经足够好了,因为我完全不知道从哪里开始。

编辑:m是整个数组可以跳过的累积步骤,不是两个单独的递增子序列之间可以跳过的步骤。

共有1个答案

尚景焕
2023-03-14

这个问题可以通过使用动态编程技术来解决。

调用输入数组<代码>数据 长度<代码> n

假设我们有一个数组dp[n][n1],其中条目dp[i][j]存储最接近的索引,从 dp[i][j]开始,递增子序列的长度从 i开始为 。如果我们有这个 dp,您的问题的结果是直接的。

现在,如何计算特定 j 的 dp[i][j]?将 i 从索引 n - 1 向后移动到 0,假设我们维护另一个数组列表[n 1]list[i] 存储所有索引 k,其子序列从 k 和长度 i 开始递增。我们需要维护 list[j] 的属性:list[j] 是递减列表,元素位于索引 xy 位于列表[j]中,则数据[x]

int[][]dp = new int[n][n + 1];
fill(dp, -1);
List<Integer>[]lists = new List[n + 1];
for(int i = n - 1; i >= 0; i--){
    for(int j = 1; j <= n; j++){
        if(j == 1){
            dp[i][j] = i;

        }else if(!list[j - 1].isEmpty()){
            int index = binary search in list[j - 1] to get the nearest index that greater than data[i];
            dp[i][j] = dp[index][j - 1];

        }
        if(dp[i][j] == -1)
           continue;
        while(data[list[j].peekLast()] <= data[i]){
        //Remove all entries which is smaller than i in list, we can easily see that all entries which is smaller than i can only end at point at least as near as end point of i.
           list[j].pollLast();
        }
        if(list[j].isEmpty() || dp[list[j].peekLast()][j] > dp[i][j]){
        //Only add entry to list if result of new entry is nearer. 
           list[j].add(i);
        }
    }
}

时间复杂度O(n^2。

 类似资料:
  • 给定一个列表{x_i},我想要找到从每个元素开始的最长的递增子序列,使得起始元素包含在子序列中。 最明显的方法是对每个元素执行通常的最长递增子序列算法,给出O(n^2logn)。这能打吗?

  • 你好,我的作业是:给定的整数序列,找到最长的子序列,它的元素是按递增顺序排列的。最多有k个异常,这意味着最多有k次,序列中的下一个数字小于前一个。输出应该是最长的子序列的长度。 我发现了许多查找LIS的例子,甚至一个允许有一个更改,但是我不知道如何用k个更改来检查。以下是一次更改后发布的链接:https://www.geeksforgeeks.org/lonth-increasing-subarr

  • 所以我用动态编程做了一个简单的python代码来解决最大递增子序列的问题。问题如下: 给定一个数组 arr 的 N 个正整数。求出给定数组的最大和递增子序列的总和。 输入:输入的第一行包含一个整数 T,表示测试用例的数量。每个测试用例的第一行是 N(数组的大小)。每个测试用例的第二行包含数组元素。 输出:对于每个测试用例,在新行中打印所需的答案。 在我的解决方案中,我正在计算一个名为“总和”的列表

  • 我在阅读了允许K个异常的最长递增子序列后创建了这个线程。我意识到提问的人并没有真正理解这个问题,因为他指的是一个链接,该链接解决了“允许一次更改的最长递增子数组”问题。所以他得到的答案实际上与李的问题无关。 假设给定一个长度为N的数组A。查找允许K个异常的最长递增子序列。 示例:N=9,K=1 A=[3,9,4,5,8,6,1,3,7] 答案:7 说明: 最长递增子序列为:3,4,5,8(或6),

  • 最长增子序列是我们熟知的问题,我用耐心算法给出了一个解决方案。 我曾想过先用我的算法,然后找到长度为N的第一个序列,但不知道该怎么做。 那么,如何从随机整数序列中找到第一个最长的递增子序列呢? 我的代码段: 我的代码返回:1 2 8 第一个序列是:3 6 8 另一个例子: 我的代码正确返回:1 2 3 基本上,只要第一个最长序列与最佳最长序列相同,我的代码就能工作。但是当你有一堆相同长度的最长序列

  • 在最多一个序列存在重复的情况下,可以将最长公共子序列问题转化为最长递增子序列问题。减少问题的过程说明在这里: 假设您有以下序列: 然后,创建一个整数序列S3,其中您必须将S2的每个元素的位置放在S1中(如果元素在S1中不存在,那么忽略那个元素)。在本例中: 这种方法是如何工作的?为什么这种约简解决了寻找最长公共子序列的问题?