在c ++中使用std :: set的最长增加子序列

时间:2013-09-01 14:04:31

标签: c++ algorithm

我在一本书中找到了LIS的代码,我不太能够证明正确性的证据。有人可以帮我解决这个问题。如果新元素不是插入新元素的最大值,那么所有代码​​都在删除集合中新插入元素旁边的元素。

    set<int> s;
    set<int>::iterator it;
    for(int i=0;i<n;i++)
    {
         s.insert(arr[i]);
             it=s.find(arr[i]);
         it++; 
         if(it!=s.end()) 
           s.erase(it);
    }
    cout<<s.size()<<endl;

n是序列的大小,arr是序列。如果我们不必找到“严格”增加的序列,我不认为以下代码将起作用。我们是否可以修改代码以查找允许相等的增加序列。

编辑:该算法仅在输入不同时才有效。

4 个答案:

答案 0 :(得分:3)

LIS有几种解决方案。 最典型的是使用动态编程的O(N ^ 2)算法,其中对于每个索引,您计算“在索引i处结束的最长增加序列”。 您可以使用聪明的数据结构或二进制搜索将其加速到O(N log N)。

您的代码会绕过此代码并仅计算LIS的长度。 考虑输入“1 3 4 5 6 7 2”,最后设置的内容为“1 2 4 5 6 7”,这不是LIS,但长度是正确的。 证据应该使用归纳法如下:

在第i次迭代之后,第j个最小元素是数组的前i个元素中长度j的递增序列的最小可能结束。

考虑输入“1 3 2”。在第二次迭代之后我们设置“1 3”,因此1是长度1的增加序列的最小可能结束,3是长度2的增加序列的最小可能结束。
在第三次迭代之后,我们设置了“1 2”,其中2是长度为2的递增序列的最小可能结束。

我希望你能自己做归纳步骤:)

答案 1 :(得分:2)

代码是LIS的O(nlogn)解决方案,但是你想找到非严格增加的序列,实现有问题,因为std :: set不允许重复元素。这是有效的代码。

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;

int main()
{
    int arr[] = {4, 4, 5, 7, 6};
    int n = 5;
    multiset<int> s;
    multiset<int>::iterator it;
    for(int i=0;i<n;i++)
    {
        s.insert(arr[i]);
        it = upper_bound(s.begin(), s.end(), arr[i]);
        if(it!=s.end()) 
            s.erase(it);
    }
    cout<<s.size()<<endl;
    return 0;
}

答案 2 :(得分:1)

证明相对简单:将s设置为排序列表。我们可以用loop invariant证明它。在算法的每次迭代之后,s[k]包含arr的最小元素,该元素在子数组中从零到{{1}的最后一个元素结束长度k的递增子序列我们到目前为止已经考虑过了。我们可以通过归纳证明这一点:

  • 在第一次迭代之后,此语句为真,因为arr将只包含一个元素,这是一个元素的一个简单的升序序列。
  • 每次迭代都可以通过以下两种方式之一更改集:在s是目前为止找到的最大元素的情况下,它可以将其扩展为1,或者用arr[i]替换现有元素,小于之前的元素。

当发生集合的扩展时,会发生这种情况,因为当前元素arr[i]可以附加到当前LIS。当替换发生在位置arr[i]时,索引为k,因为arr[i]结束了长度为arr[i]的递增子序列,并且小于或等于旧的k,用于结束长度s[i]之前的“最佳”升序子序列。

有了这个不变量,很容易看出k包含尽可能多的元素,而不是整个s耗尽后arr的最长升序子序列。

答案 3 :(得分:-1)

问题陈述:

  For A(n) :a0, a1,….an-1 we need to find LIS

  Find all elements in A(n) such that, ai<aj and i<j.
  For example: 10, 11, 12, 9, 8, 7, 5, 6
  LIS will be 10,11,12

这是基于DP的O(N ^ 2)解决方案。

1 Finding SubProblems
Consider D(i): LIS of (a0 to ai) that includes ai as a part of LIS.
2 Recurrence Relation
D(i) = 1 + max(D(j) for all j<i) if ai > aj
3 Base Case
D(0) = 1;

查看代码的链接: https://innosamcodes.wordpress.com/2013/07/06/longest-increasing-subsequence/