动态规划之最长递增子序列(Longest Increasing Subsequence)

最长递增子序列详解(longest increasing subsequence 一个各公司都喜欢拿来做面试笔试题的经典动态规划问题,互联网上也有很多文章对该问题进行讨论,但是我觉得对该问题的最关键的地方,这些讨论似乎都解释的不很清楚,让人心中不快,所以自己想彻底的搞一搞这个问题,希望能够将这个问题的细节之处都能够说清楚。 对于动态规划问题,往往存在递推解决 阅读详情

原文地址:http://www.geeksforgeeks.org/dynamic-programming-set-3-longest-increasing-subsequence/

We have discussed Overlapping Subproblems and Optimal Substructure properties in Set 1 and Set 2respectively.

我们已经在前讨论了重叠的子问题与最优的子结构属性。

Let us discuss Longest Increasing Subsequence (LIS) problem as an example problem that can be solved using Dynamic Programming.

我们来讨论一下用动态规划来解决最长递增子序列(LIS)作为例子。

The longest Increasing Subsequence (LIS) problem is to find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order. For example, length of LIS for { 10, 22, 9, 33, 21, 50, 41, 60, 80 } is 6 and LIS is {10, 22, 33, 50, 60, 80}.

最长递增子序列问题是从给定的字符串中找到长度最长的子序列(注意:与自字符串的区别),这样子序列中所有的元素都是以递增的顺序排过序的。例如:{ 10, 22, 9, 33, 21, 50, 41, 60, 80 } 的LIS长度为6,其中LIS为 {10, 22, 33, 50, 60, 80}。

Optimal Substructure:
Let arr[0..n-1] be the input array and L(i) be the length of the LIS till index i such that arr[i] is part of LIS and arr[i] is the last element in LIS, then L(i) can be recursively written as.

L(i) = { 1 + Max ( L(j) ) } where j < i and arr[j] < arr[i] and if there is no such j then L(i) = 1

 To get LIS of a given array, we need to return max(L(i)) where 0 < i < n So the LIS problem has optimal substructure property as the main problem can be solved using solutions to subproblems,
 

最优的子结构:

arr[0..n-1] 作为输入数组,L(i)是到下标i的LIS的长度,这样arr[i]是LIS的部分,arr[i]是LIS中最后的元素,所以L(i)可以递归地写为:

L(i) = { 1 + Max ( L(j) ) } where j < i and arr[j] < arr[i] and if there is no such j then L(i) = 1

为了得到给定数组的LIS,我们需要返回max(L(i)) where 0 < i < n,所以LIS具有最优子结构的属性,主问题可以通过解决子问题来得到解决。

Overlapping Subproblems:

Following is simple recursive implementation of the LIS problem. The implementation simply follows the recursive structure mentioned above. The value of lis ending with every element is returned using max_ending_here. The overall lis is returned using pointer to a variable max.

重叠的子问题:

下面是LIS问题的简单递归实现。这个实现简单第遵循了上面提到的递归。以每个元素结尾的LIS值用max_ending_here返回。总体的LIS用一个纸箱变量max的指针返回的。

C++代码:

/* A Naive C/C++ recursive implementation of LIS problem */
#include<stdio.h>
#include<stdlib.h>
 
/* To make use of recursive calls, this function must return
   two things:
   1) Length of LIS ending with element arr[n-1]. We use
      max_ending_here for this purpose
   2) Overall maximum as the LIS may end with an element
      before arr[n-1] max_ref is used this purpose.
   The value of LIS of full array of size n is stored in
   *max_ref which is our final result */
int _lis( int arr[], int n, int *max_ref)
{
    /* Base case */
    if (n == 1)
        return 1;
 
    // 'max_ending_here' is length of LIS ending with arr[n-1]
    int res, max_ending_here = 1; 
 
    /* Recursively get all LIS ending with arr[0], arr[1] ...
       arr[n-2]. If   arr[i-1] is smaller than arr[n-1], and
       max ending with arr[n-1] needs to be updated, then
       update it */
    for (int i = 1; i < n; i++)
    {
        res = _lis(arr, i, max_ref);
        if (arr[i-1] < arr[n-1] && res + 1 > max_ending_here)
            max_ending_here = res + 1;
    }
 
    // Compare max_ending_here with the overall max. And
    // update the overall max if needed
    if (*max_ref < max_ending_here)
       *max_ref = max_ending_here;
 
    // Return length of LIS ending with arr[n-1]
    return max_ending_here;
}
 
// The wrapper function for _lis()
int lis(int arr[], int n)
{
    // The max variable holds the result
    int max = 1;
 
    // The function _lis() stores its result in max
    _lis( arr, n, &max );
 
    // returns max
    return max;
}
 
/* Driver program to test above function */
int main()
{
    int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
    int n = sizeof(arr)/sizeof(arr[0]);
    printf("Length of lis is %d\n",
           lis( arr, n ));
    return 0;
}
运行结果:

Length of lis is 5
Considering the above implementation, following is recursion tree for an array of size 4. lis(n) gives us the length of LIS for arr[].

想一下以上实现,下面是一个大小为4的递归树。lis(n)给出了数组arr[]的LIS的长度。

              lis(4)
         /        |     \
      lis(3)    lis(2)   lis(1)
      /   \        /
   lis(2) lis(1) lis(1)
   /
lis(1)

We can see that there are many subproblems which are solved again and again. So this problem has Overlapping Substructure property and recomputation of same subproblems can be avoided by either using Memoization or Tabulation. Following is a tabluated implementation for the LIS problem.

我们可以看到许多子问题一遍又一遍地解决。所以这个问题有重叠子结构的属性,可以通过用记忆法或者制表法来避免重复计算相同的子问题。下面是LIS问题的制表法实现。

/* Dynamic Programming C/C++ implementation of LIS problem */
#include<stdio.h>
#include<stdlib.h>
 
/* lis() returns the length of the longest increasing
  subsequence in arr[] of size n */
int lis( int arr[], int n )
{
    int *lis, i, j, max = 0;
    lis = (int*) malloc ( sizeof( int ) * n );
 
    /* Initialize LIS values for all indexes */
    for (i = 0; i < n; i++ )
        lis[i] = 1;
 
    /* Compute optimized LIS values in bottom up manner */
    for (i = 1; i < n; i++ )
        for (j = 0; j < i; j++ )
            if ( arr[i] > arr[j] && lis[i] < lis[j] + 1)
                lis[i] = lis[j] + 1;
 
    /* Pick maximum of all LIS values */
    for (i = 0; i < n; i++ )
        if (max < lis[i])
            max = lis[i];
 
    /* Free memory to avoid memory leak */
    free(lis);
 
    return max;
}
 
/* Driver program to test above function */
int main()
{
    int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
    int n = sizeof(arr)/sizeof(arr[0]);
    printf("Length of lis is %d\n", lis( arr, n ) );
    return 0;
}
输出:

Length of lis is 5

Note that the time complexity of the above Dynamic Programming (DP) solution is O(n^2) and there is a O(nLogn) solution for the LIS problem. We have not discussed the O(n Log n) solution here as the purpose of this post is to explain Dynamic Programming with a simple example. See below post for O(n Log n) solution.

Longest Increasing Subsequence Size (N log N)

注意到上面的动态规划(DP)解决方案的时间复杂度是 O(n^2) ,并且对于这个问题还有O(nLogn) 时间复杂度的解决方案。我们在这里还没有讨论O(nLogn)的方法作为这一章解释动态规划的例子。下面一章将看到O(nLogn) 的方法。






利用ADS设计射频功率放大器 利用ADS设计射频功率放大器 任务: 用飞思卡尔公司的功率放大器芯片ATF27s006NT1设计射频功放,芯片频率范围可达450MHz-3.6GHz。 功放指标: (1) 工作频率:500MHz (2) 增益:G>20dB (3) 电源:+28V (4) 最大输出功率:2W(33dBm) 设计思路 (1)安装DesignKit模型; (2)直流DC扫描; (3)稳定性分析; (4)偏置电路设计及整... 阅读详情

相关推荐

CST新手必看:共面波导色散曲线绘制全流程(附参数设置避坑指南)

本文详细介绍了CST Microwave Studio中绘制共面波导色散曲线的全流程操作,特别针对新手常见的边界条件设置错误、参数扫描失效等问题提供解决方案。通过模型建立、边界条件设置、本征模求解器配置等步骤,帮助工程师快速掌握CPW色散特性分析方法,并附有参数设置避坑指南,提升高频电路设计效率。

tomato的博客 926

如何给dropdownlist动态赋初始值_动态规划设计方法:归纳思想解决 LIS

读完本文,你可以去力扣拿下如下题目:300.最长上升子序列-----------也许有读者看了前文 动态规划详解,学会了动态规划的套路:找到了问题的「状态」,明确了 dp 数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?不要担心,动态规划的难点本来就在于寻找正确的状态转移方程,本文就借助经典的「最长递增子序列问题」...

weixin_39619635的博客 619

js代码-求最长递增子序列

js代码-求最长递增子序列

JSCPC2018 I. Longest Increasing Subsequence

I. Longest Increasing Subsequence Bobo has a sequence a1,a2,…,an. Let f(x) be the length of longest strictly increasing subsequence after replacing all the occurrence of 0 with x. He would like to ...

dream_three的博客 728

动态规划——最长递增子序列

前言 最长递增子序列动态规划中最经典的问题之一,该问题描述的是在一个已知序列{A1,A2,...,An}中,取出若干元素(不必连续)组成一个新的序列{Ax,...,Ay},子序列的各个数先后顺序保持不变,且对子序列中的任意下标x<y有Ax<Ay,则称该子序列为原序列的一个递增子序列最长递增子序列就是原序列的所有递增子序列最长的那个。 思路 令dp[i]表示以A[i]作为末尾的最长递增子序列的长度。于是,通过设置这么一个数组,最长递增子序列的长度便是数组dp中的最大值。 由于dp[i]

白给、少年 9065

最长递增子序列动态规划

问题描述: 输入一组乱序的数据,输出这组数据的最长递增序列,如输入X[ ] = (2 8 9 4 6 1 3 7 5 10),则输出(2 4 6 7 10) 求解最长递增子序列的问题,我们考虑用动态规划,而动态规划,我们就得弄清楚子问题,最终的解决办法如下: 1.在遍历数据的过程中,记录下排第几的数是哪一位,用L[ ]数组来记录,用len来表示当前的最高位的位数; 2.遍历遇到比最高位还大的数X...

qq_43764726的博客 335

Python 中的最长递增子序列

我们将学习什么是子序列,以及如何使用 Python 中的 n 平方方法和二分搜索方法计算数组中最长递增子序列

迹忆客 1079

【转】动态规划最长递增子序列Longest Increasing Subsequence

转自:https://www.cnblogs.com/coffy/p/5878915.html 设f(i)表示L中以ai为末元素的最长递增子序列的长度。则有如下的递推方程: 这个递推方程的意思是,在求以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<i且aj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的...

aaa2549769750的博客 345

Longest Increasing Subsequence最长递增子序列动态规划+二分查找)

Given an unsorted array of integers, find the length of longest increasing subsequence. For example, Given [10, 9, 2, 5, 3, 7, 101, 18], The longest increasing subsequence is [2, 3, 7, 101], th

lzf的博客 1569

动态规划最长递增子序列(longest increasing subsequence)

1,什么是动态规划? 在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。当然,各个阶段决策的选取不是任意确定的,它依赖于当前面临的状态,又影响以后的发展,当各个阶段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线,这种把一个问题看作是一个前后关联具有链状结构的多阶段过程就称为多阶段

记录每一个小阶段的学习心得,持之以恒! 6332

[动态规划] 最长递增子序列Longest Increasing Subsequence

1.复杂度为O(n^2) const int maxn=100020; const int inf=0x3f3f3f3f; int dp[maxn];//以a[i]为结尾的最长自增子序列长度 int a[maxn]; int n; int LIS(int a[],int n)//最长上升子序列 { int m; dp[0]=1; for(int i=1;i<n;i++)

逆风的方向 更适合飞翔 2279

HDU 6284 Longest Increasing Subsequence(LIS+思维)

Longest Increasing SubsequenceTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 232    Accepted Submission(s): 57Problem DescriptionBobo has a seq...

咸鱼有梦想 845

(c语言易懂版)算法:第k个最长递增子序列

某个整数序列中,去掉0个以上的数字后,剩余的部分就是原序列的子序列。例如,{7,4,9}、{10,4}、{10,9}等是{10,7,4,9}的子序列。而序列{10, 4, 7}具有不同于原序列的排列顺序,因而不属于{10,7,4,9}的子序列。严格递增子序列称为递增子序列。序列的递增子序列中,最长的序列称为最大递增子序列LIS)。例如:{5,20,21,22,8,9,10}的最大递增子序列是{5,8,9,10}。(不唯一) 给出以不同数字组成(无重复数字)的序列时,请编写程序,计算此序列的LIS中按照字

weixin_46013817的博客 1613

最长上升子序列Longest increasing subsequence

  问题描述         对于一串数A={a1a2a3…an},它的子序列为S={s1s2s3…sn},满足{s1&lt;s2&lt;s3&lt;…&lt;sm}。求A的最长子序列的长度。 动态规划法 算法描述:         设数串的长度为n,L[i]为以第i个数为末尾的最长上升子序列的长度,a[i]为数串的第i个数。         L[i]的计算方法为:从前i-1个数中找出满足a...

无限迭代中...... 787

LeetCode: 873. Length of Longest Fibonacci Subsequence

LeetCode: 873. Length of Longest Fibonacci Subsequence 题目描述 A sequence X_1, X_2, …, X_n is fibonacci-like if: n &gt;= 3 X_i + X_{i+1} = X_{i+2} for all i + 2 &lt;= n Given a strictly increasing ar...

杨领well的专栏 1048

c++中的最长递增子序列Longest Increasing Subsequence)(算法章完结)

hello大家好啊,我是文宇。今天是最后一篇算法(暂时性的,以后可能还有)算法章完结。预告:下周会出 《一周速通c++(顺序,选择,循环篇)》。后面还有函数,数组,字符串等。

文宇的博客 731

最长递增子序列问题

一 问题描述 设序列L = 是长度为n的序列,L的一个递增序列描述为:, 其中下标序列 是 递增的, 子序列 也是递增的。此递增序列的长度为 k 二 解法1, 转化为LCS问题 先把序列 L 按照从小到大的顺序排列, 得到另一个序列S,再求L和S的最长公共子序列

kenby的专栏 1万+

最长递增子序列Longest Increasing Subsequence

定义 最长上升子序列Longest Increasing SubsequenceLIS),在计算机科学上是指一个序列中最长的单调递增子序列。 问题描述 给定一个长度为 N 的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为 5 的数组{5, 6, 1, 2, 8},则其最长的单调递增子序列为 {5,6,8},长度为 3。 解法 动态规划 时间复杂度 该方法的时间复杂度为 。 实现过程 下面我们用一个实例来分析一下动态规划求解 LIS 的整个过程。

努力中的老周的专栏 4364

求数组中最长递增子序列 (python)

题目要求:写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中最长递增子序列的长度。注意:这里要求的是子序列子序列是不要求连续的。 解法 1 根据无后效性的定义我们知道,将各个阶段按一定的次序排序好之后,对于某个给定阶段的状态来说,它以前的各个阶段的状态无法直接影响它未来的一个决策。而只能间接地通过当前状态来影响。同样地,本题就符合后效性的定义。可以采用动态规划的方法来做。 通过数学规律来分析目标串:1,-1,2,-3,4,-5,6,-7 使用i来表示当前遍历的位置。 当i等于1时 ..

qq_43211230的博客 2127

LeetCode--Longest Increasing Subsequence最长递增子序列)Python

题目: 给定一串数组,返回其中的最长递增子序列的长度。例如:给定数组[10, 9, 2, 5, 3, 7, 101, 18],则其最长递增子序列为[2, 3, 7, 101],返回长度4. 解题思路: 使用动归。用Dp[i]来保存从0-i的数组的最长递增子序列的长度。如上数组Dp[0]=1,Dp[1]=1,Dp[2]=1,Dp[3]=2,Dp[4]=2。。。计算Dp[i]的值可以对Dp[i]

诚实的小小乐 3532

2000年为基期GDP平减方法以及252个城市GDP数据

里面有详细的人均GDP和GDP平减计算方法,简单易懂,写论文的过程中整理有任何不一致的意见,欢迎交流祝大家学术生活一帆风顺

上一篇: 动态规划之最优的子结构属性(Optimal Substructure Property)
下一篇: SQL删除表中的重复记录(多个字段),只留一条。
K.Sun
博客等级 码龄10年 181粉丝 273原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值