LIS学习笔记(两种算法)

Posted pprp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LIS学习笔记(两种算法)相关的知识,希望对你有一定的参考价值。

2017-09-02 10:34:21

writer:pprp

最长上升子序列,具体分析看代码:O(n^2)的做法,dp的思想

代码如下:

/*
@theme:LIS最长上升子序列
@writer:pprp
@begin:10:00
@end:10:15
@declare复杂度为O(n^2)
@error:dp[i] = MAX(dp[j]+1,dp[i]),dp[i] = 1初始化为1
@date:2017/9/2
*/

#include <bits/stdc++.h>

using namespace std;

/*
未优化的最长上升子序列
f(i)代表从头到i的位置最长上升子序列的长度
if( i < n && arr[i] < arr[n] )
    f(n) = max(f(i))+ 1;
dp[i]是如果取到arr[i]的时候的最长上升子序列
*/

int dp[10010],arr[10010];

int MAX(int a, int b)
{
    return a > b ? a : b;
}

int main()
{
    int N;
    while(cin >> N && N)
    {
        int max = 0;
        for(int i = 0 ; i < N ;i++)
        {
            dp[i] = 1;
            cin >> arr[i];
            for(int j = 0 ;j < i ; j++)
            {
                if(arr[j] < arr[i])
                    dp[i] = MAX(dp[j] + 1, dp[i]);
            }
            max = MAX(max,dp[i]);
        }
        cout << max << endl;
    }
    return 0;
}

2、采用了优化,记录了可能被选中的点,将其记录在tmp数组中,再从从其中进行查找

/*
@theme:tmp最长上升子序列
@writer:pprp
@begin:10:00
@end:14:32
@declare复杂度为O(n^2)
@error:dp[i] = MAX(dp[j]+1,dp[i]),dp[i] = 1初始化为1
@date:2017/9/2
*/

#include <bits/stdc++.h>

using namespace std;

int arr[10010],tmp[10010];
int len;

/*
状态定义:用到tmp数组
tmp[i]:代表的是对于所有长度为i的LIS,他的结果最小有可能是多少,
       如果越小那就越容易被取到
tmp中的元素是严格递增的
状态转移:
        if( dp[j] = i )
            tmp[i] = min(arr[j])
结果查找--用二分的方法去找
if(tmp[i] < arr[n] && tmp[i+1] >= arr[n] )
    f[n] = i+1 .... i 代表的是长度

*/

//二分查找,在tmp中进行二分查找arr[i]
//对tmp数组进行更新
void bisearch(int x)
{
    int left=1,mid,right=len;
    while(left<=right)
    {
        mid=(left+right)>>1;
        if(tmp[mid]<x)
            left=mid+1;
        else
            right=mid-1;
    }
    tmp[left]=x;
}

int main()
{
    int N;
    while(cin >> N && N)
    {
        len=1;
        cin >> arr[0];
        tmp[len]=arr[0];

        for(int i=1; i<N; i++)
        {
            scanf("%d",&arr[i]);

            if(arr[i] > tmp[len])//如果当前i指向的arr的值大于tmp当前的值
            {
                len++;
                tmp[len]=arr[i];
            }//向tmp数组中加入arr的值
            else
                bisearch(arr[i]);//在tmp中进行查找找到的就将其更新
            //如果用lower_bound的话就这样:
            //*lower_bound(tmp,tmp+len,arr[i]) = arr[i];
        }
        printf("%d\n",len);
    }
    return 0;
}

 

以上是关于LIS学习笔记(两种算法)的主要内容,如果未能解决你的问题,请参考以下文章

day6,笔记内容

学习笔记:python3,代码片段(2017)

LIS(最长上升子序列)

学习笔记:二分法查找的递归和非递归两种算法

机器学习实战笔记-K近邻算法3(手写识别系统)

长尾预测效果不好怎么办?试试这两种思路