最长上升子序列

基于最长上升子序列 LIS


求最长上升子序列有两种做法 求最长上升子序列有两种做法 求最长上升子序列有两种做法
一种是 n 2 复杂度的线性 d p 一种是n^2复杂度的线性dp 一种是n2复杂度的线性dp
另一种是 O ( n l o g n ) 复杂度的贪心 + 二分 另一种是O(nlogn)复杂度的贪心+二分 另一种是O(nlogn)复杂度的贪心+二分

贪心+二分做法

整体思路就是维护一个 l o w [ ] 数组,让数组长度等于当前最长子序列长度 整体思路就是维护一个low[]数组,让数组长度等于当前最长子序列长度 整体思路就是维护一个low[]数组,让数组长度等于当前最长子序列长度
用 a n s 表示当前 l o w 数组长度 用ans表示当前low数组长度 ans表示当前low数组长度
当当前值大于 l o w [ a n s ] 时 l o w [ + + a n s ] = 当前值 当当前值大于low[ans]时 low[++ans] = 当前值 当当前值大于low[ans]low[++ans]=当前值
当当前值小于 l o w [ a n s ] 时利用二分找到在 l o w 数组中当前值所在的位置然后替换为当前值 当当前值小于low[ans]时 利用二分找到在low数组中当前值所在的位置然后替换为当前值 当当前值小于low[ans]时利用二分找到在low数组中当前值所在的位置然后替换为当前值
l o w [ f i n d ( 当前值 ) ] = 当前值 low[find(当前值)]=当前值 low[find(当前值)]=当前值
目的就是保证 l o w 数组是当前最长的上升子序列 目的就是保证low数组是当前最长的上升子序列 目的就是保证low数组是当前最长的上升子序列

代码


#include

using namespace std;

const int N = 1e3 + 10;

typedef long long ll;

ll low[N], arr[N];

int n;

int find(ll x, int len)
{
    int l = 1;
    int r = len;
    while(l < r)
    {
        int mid = l + r >> 1;
        
        if(low[mid] >= x)
        {
            r = mid;
        }
        else l = mid + 1;
    }
    
    return l;
}

int main()
{
    cin >> n;
    
    for(int i = 1; i <= n; i ++)
    {
        scanf("%lld", &arr[i]);
    }
    
    int ans = 1;
    
    low[ans] = arr[1]; //一开始第一个数就是最长上升子序列
    
    for(int i = 2; i <= n; i ++)
    {
        if(arr[i] > low[ans])
        {
            low[++ans] = arr[i];
        }
        else
        {
            low[find(arr[i],ans)] = arr[i];
        }
    }
    
    cout << ans << endl;
    
    return 0;
}


线性dp做法

最长上升子序列_第1张图片


#include

using namespace std;

const int N = 1e4 + 10;

typedef long long ll;

ll arr[N];

int f[N];

int n;

int main()
{
    cin >> n;
    
    for(int i = 1; i <= n; i ++)
    {
        scanf("%lld", &arr[i]);
    }
    
    int res = 0;
    
    for(int i = 1; i <= n; i ++)
    {
        f[i] = 1; //初始化 每个数结尾最开始都是长度为1的LIS
        
        for(int j = 1; j < i; j ++)
        {
            if(arr[i] > arr[j])
            f[i] = max(f[i], f[j] +1);
        }
    }
    
    for(int i = 1; i <= n; i ++)
    {
        res = max(res, f[i]);
    }
    
    cout << res << endl;
    
    return 0;
}

你可能感兴趣的:(动态规划,算法,动态规划,贪心算法)