[英]DP: Longest Increasing Subsequence Thought Process & Solution
对于最长增长子序列问题,我设想保留一个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}
这样,DP阵列的最后一个条目将是当前阵列的LIS。 这将成为我们的不变式,因此,当我们达到终点时,可以确保最后的值是我们唯一需要的值。 然后让我想到,在遍历具有DP类感觉的数组时,下一个值不依赖于该数组中以前列出的任何值,因此此方法与维护maxLIS
变量(一种模式)相同我已经在许多O(n)
解决方案中看到过。 因此,我最接近正确的解决方案如下:
1.)将输入数组/向量的副本保存为old
2.)对原始输入数组进行排序
3.)遍历排序后的数组,每当下一个值(该值应大于当前值)出现在原始数组中的当前值之前,变量就longest
递增一个。
4.)返回longest
代码是〜this:
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;
}
在使用find
方法的情况下(我假设是线性操作),我们可以通过制作一个数据结构来存储值的原始索引以及值本身来进行常量操作,因此我们无需执行任何操作遍历以查找原始数组( old
)中元素的索引。 我相信这将是一个O(nlog(n))
解决方案,但是此输入数组失败: [1,3,6,7,9,4,10,5,6]
。 在这里检查
最终,我进行了一些研究,发现我读过的所有解决方案指南的事实都是,他们的解决方案使DP数组的值不按顺序排列,而是像这样:DP数组中的值表示递增的长度子序列,该子序列的最后一个值是originalArray[index]
的值。
更明确地说,
array => {5, 6, 7, 1, 2, 3}
dp => {1, 2, 3, 1, 2, 3}
此处,其中5是递增子序列的最后一个值,在它之前没有值,因此它的长度必须为1。如果6是递增子序列的最后一个值,我们必须查看它之前的所有值以确定a以6结尾的子序列即可。 它之前只能有5个,因此是到目前为止增加的最长子序列2。这将继续,您将在DP数组中返回最大值。 该解决方案的时间复杂度为O(n^2)
,即标准天真解决方案。
我很好奇如何正确思考这个问题。 我想微调我的思维过程,以便我可以从头开始提出一个最佳解决方案(至少是目标),所以我想知道
1.)这个问题的什么属性应该触发我使用与使用它不同的DP阵列? 事后看来,我的原始方式仅相当于保留max变量,但即使那样,我仍然很难看到该问题的性质,这会触发思想“嘿,我的DP数组中索引为i的条目的值应该是以originalArray [i]结尾的递增子序列。 我正在努力查看该如何解决。
2.)是否可以使我建议的O(nlog(n))
解决方案正常工作? 我知道存在O(nlog(n))
解决方案,但是由于我无法正常工作,因此我认为我需要朝正确的方向轻推。
我承认,这是一个有趣的问题,我没有确切的答案,但是我想我可以向您介绍正确的方向。 所以就这样:
面对这样的困境,我通常会转向基础知识。 就像您的情况一样,请经过动态编程的定义。 它具有两个属性:
- 重叠子问题
- 最佳子结构。
您可以轻松找到标准解决方案中反映的这些属性,但您的却不是。 您可以在cormen中阅读有关它们的信息,也可以在DP的上下文中对其进行谷歌搜索。
我认为您的解决方案不是DP,您只是找到了某种模式,并且您正在尝试根据该模式进行解决。 如果您没有得到解决方案,则意味着您的模式错误或解决方案无所适从。 在这种情况下,请尝试从数学上证明您正在观察的模式是正确的,并证明该解决方案也应该有效。
在我研究您的解决方案时,请给我更多时间,但同时您也可以尝试为您的解决方案开发证明。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.