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

DP:最长递增子序列思维过程及解法

舒宏富
2023-03-14

对于最长的子序列递增问题,我设想保持一个总是有序的DP数组,将最大值保持在最远端。看起来像这样的东西:

{1, 1, 2, 3, 3, 4, 5, 6, 6, 6}

我得出第一个不正确的解决方案的思路是,我们想从第一个元素开始查看整个数组,计算LIS,然后在数组末尾递增地添加一个值。在执行此操作时,我们将DP数组中的LIS增量计算为旧子数组加上我们添加的新元素的LIS。这意味着在dp数组的索引i处存在长度为i的子数组的LCS值。

更清楚地说

array => {5, 6, 7, 1, 2, 3, 4}
dp    => {1, 2, 3, 3, 3, 3, 4}

2.)对原始输入数组进行排序

3.)遍历已排序数组,每次下一个值(应大于当前值`)出现在原始数组中的当前值之前时,将变量longth递增1。

4.)返回最长

int lengthOfLIS(vector<int>& seq) {
  if (!seq.size()) return 0;
  vector<int> old = seq;

  sort(seq.begin(), seq.end());

  int longest = 1;

  for (int i = 1; i < seq.size(); ++i) {
    if (seq[i] > seq[i-1] && find(old.begin(), old.end(), seq[i]) - old.begin() > find(old.begin(), old.end(), seq[i-1]) - old.begin()) longest++;
  }
  return longest;
}
array => {5, 6, 7, 1, 2, 3}
dp    => {1, 2, 3, 1, 2, 3}

这里,5是递增子序列的最后一个值,前面没有值,所以它的长度必须为1。如果6是递增子序列的最后一个值,我们必须查看它之前的所有值,以确定以6结尾的子序列可以有多长。在它之前只有5个,从而使迄今为止最长的递增子序列为2。继续这样做,然后返回DP数组中的最大值。此解决方案的时间复杂度为O(n^2),是标准的朴素解决方案。

我很好奇我怎样才能正确地思考这个问题。我想对我的思维过程进行微调,这样我就可以从头开始想出一个最优的解决方案(这至少是我的目标),所以我想知道

1.)这个问题的什么属性应该触发我以不同的方式使用一个DP数组?事后看来,我最初的方法只是简单地等价于保留一个max变量,但即使这样,我也很难看到这个问题的一个属性会触发这样的想法:嘿,我的DP数组中索引I处的一个条目的值应该是以originalarray[I]结尾的递增子序列的长度。我很难看到我应该如何得出这个结果。

2.)是否有可能使我提出的O(nlog(n))解决方案起作用?我知道存在一个O(nlog(n))解决方案,但由于我不能使我的解决方案起作用,我认为我需要朝正确的方向推一下。

共有1个答案

秦伯寅
2023-03-14

我承认,这是一个有趣的问题,我没有确切的答案,但我想我可以给你一个正确的方向。所以是这样的:

在面对这样的困境时,我通常会求助于基础知识。就像在您的例子中一样,了解动态编程的定义。它有两个属性:

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

  • 我正在解决一个程序设计的挑战,在一个2D NxN矩阵中寻找最长的递增子序列的长度。在序列的每个元素中,行和列都必须增加(不需要连续)。本文用动态规划方法求解,但它是O(n^4),效率低。然而,在O(n^3)中有许多解。一种这样的解决办法是: 有人能解释一下它的工作原理或其他O(n^3)方法吗?我根本听不懂:(。

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

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

  • 我为最长的递增子序列编写了一个递归解,它运行得非常好。但是当我在同一个代码上应用dp时,它给出了不同的答案。问题链接:https://practice.geeksforgeeks.org/problems/longest-increasing-subsequence-1587115620/1递归代码: DP代码: 我不知道我做错了什么?对于这个测试用例6(n)6 3 7 4 6 9(arr[]),

  • 我为最长的递增子序列生成了以下代码: 输入:nums=[10,9,2,5,3,7,101,18] 输出:4 说明:最长的递增子序列是[2,3,7,101],因此长度为4。 有人能帮我理解这句话吗 三个点的意义是什么?正如我们所知,映射生成键值对,映射与切片一起做什么?