算法实践--最长递增子序列(Longest Increasing Subsquence)

什么是最长递增子序列(Longest Increasing Subsquence)

对于一个序列{3, 2, 6, 4, 5, 1},它包含很多递增子序列{3, 6}, {2,6}, {2, 4, 5}, {1}

其中最长的递增子序列是{2, 4, 5}

问题:对于长度为N的矢量D,如何找到它的最长递增子序列

一个简单的算法

for (i=N; i>0; --i) {1. 找到所有长度为i的子序列;   //复杂度为(N!)/(i!)(N-i)!    O(exp(N))
   2. 判断是否其中有一个为递增子序列}

动态规划算法

基本思想:将一个复杂问题,分解为更小的子问题

首先定义LIS[i],表示以D[i]结尾的最长子序列

对于矢量D = {3, 2, 6, 4, 5, 1};

LIS[0]:  3
LIS[1]:  2
LIS[2]:  2,6
LIS[3]:  2,4
LIS[4]:  2,4,5
LIS[5]:  1

给出递推公式

LIS[0] = D[0]

LIS[i] = MAX(LIS[j] | j <i, D[j] <D[i]) + "D[i]"

解释:

当我们求LIS[i]时,对于任意j<i,LIS[j]都已知

在所有已知的LIS中,找出结尾的元素值小于D[i],长度最长的一个

然后在后面加上D[i]元素,即为LIS[i]

示例C++代码

using namespace std;

void prt(vector<int>& arr, string msg = "") {
    cout << msg << " ";
    for  (auto i: arr) {
        cout << i << " ";
    }
    cout << endl;
}

void calc_LIS(vector<int>& D) {
    vector< vector<int> > L(D.size());  // The longest increasing subsequence ends with D[i]

   L[0].push_back(D[0]);

    for (int i=1; i<D.size(); i++) {
        for(int j=0; j<i; j++) {
            if ( (D[j] < D[i]) && ( L[i].size() < L[j].size() ) ) {
                L[i] = L[j];
            }
        }
      L[i].push_back(D[i]);
    }

    for (auto x: L) {
        prt(x);
    }
}

int main() {
    int a[] = {3, 2, 6, 4, 5, 1};
    vector<int> arr(a, a + sizeof(a)/sizeof(a[0]));

    prt(arr, "Data In:");
    calc_LIS(arr);

    return 0;
}

复杂度分析

时间复杂度是O(N^2)

动态规范的基本思想是以一定的空间开销,显著缩短时间开销

原文地址:https://www.cnblogs.com/logchen/p/10260913.html

时间: 2024-07-31 12:52:50

算法实践--最长递增子序列(Longest Increasing Subsquence)的相关文章

最长递增子序列(Longest increasing subsequence)

问题定义: 给定一个长度为N的数组A,找出一个最长的单调递增子序列(不要求连续). 这道题共3种解法. 1. 动态规划 动态规划的核心是状态的定义和状态转移方程.定义lis(i),表示前i个数中以A[i]结尾的最长递增子序列的长度.可以得到以下的状态转移方程: d(i) = max(1, d(j) + 1), 其中j < i,且A[j] <= A[i] 程序实现: int longestIncreasingSubsequence(vector<int> nums) { if (nu

(算法)最长递增子序列

问题: Given an array of N integer, find the length of the longest increasing subsequence. For example, given [1,-5,4,5,10,-1,-5,7], the longest increasing subsequence is length 4.(1,4,510) 思路: 1.枚举 枚举数组所有的子序列,然后判断它们是否为递增子序列(回溯法). 2.转化 将数组排序,然后找出新数组和旧数组

[Swift]LeetCode329. 矩阵中的最长递增路径 | Longest Increasing Path in a Matrix

Given an integer matrix, find the length of the longest increasing path. From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed). E

nlog(n)解动态规划--最长上升子序列(Longest increasing subsequence)

最长上升子序列LIS问题属于动态规划的初级问题,用纯动态规划的方法来求解的时间复杂度是O(n^2).但是如果加上二叉搜索的方法,那么时间复杂度可以降到nlog(n).  具体分析参考:http://blog.chinaunix.net/uid-26548237-id-3757779.html 代码: #include <iostream> using namespace std; int LIS_nlogn(int *arr, int len) { int *LIS = new int[len

最长上升子序列Longest Increasing Subsequence

给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是?[2,3,7,101],它的长度是 4. 方法1:时间复杂度n2,容易想到,记录数组中每个元素作为上升子序列最后一个元素的最大长度. import java.math.*; class Solution { public int lengthOfLIS(int[] nums) { int[] res = new int[nums.length

LeetCode 673. Number of Longest Increasing Subsequence 最长递增子序列的个数 (C++/Java)

题目: Given an unsorted array of integers, find the number of longest increasing subsequence. Example 1: Input: [1,3,5,4,7] Output: 2 Explanation: The two longest increasing subsequence are [1, 3, 4, 7] and [1, 3, 5, 7]. Example 2: Input: [2,2,2,2,2] O

(转载)最长递增子序列 O(NlogN)算法

原博文:传送门 最长递增子序列(Longest Increasing Subsequence) 下面我们简记为 LIS. 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素.注意d中元素是单调递增的,下面要用到这个性质.首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么len++,d[len] = a[i];否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],

最长递增子序列 O(NlogN)算法

https://www.felix021.com/blog/read.php?entryid=1587&page=3&part=1 感谢作者! 标题:最长递增子序列 O(NlogN)算法 出处:Blog of Felix021 时间:Wed, 13 May 2009 04:15:10 +0000 作者:felix021 地址:https://www.felix021.com/blog/read.php?1587  内容: 今天回顾WOJ1398,发现了这个当时没有理解透彻的算法. 看了好久

算法--字符串:最长递增子序列LIS

转自:labuladong公众号 很多读者反应,就算看了前文 动态规划详解,了解了动态规划的套路,也不会写状态转移方程,没有思路,怎么办?本文就借助「最长递增子序列」来讲一种设计动态规划的通用技巧:数学归纳思想.  最长递增子序列(Longest Increasing Subsequence,简写 LIS)是比较经典的一个问题,比较容易想到的是动态规划解法,时间复杂度 O(N^2),我们借这个问题来由浅入深讲解如何写动态规划. 比较难想到的是利用二分查找,时间复杂度是 O(NlogN),我们通过