动态编程之最长增加的子序列

题目:让我们讨论最长增加子序列(LIS)问题作为一个可以使用动态规划解决的例子问题。最长增加子序列(LIS)问题是查找给定序列的最长子序列的长度,使得子序列的所有元素按升序排列。例如,{10,22,9,33,21,50,41,60,80}的LIS长度是6,LIS是{10,22,33,50,60,80}。

这句话听起来是不是很绕? 简单来说,就是对一个数组进行大小比较,如果后面那个值大于当前值,则加1,如果后面那个值小于当前的话,则进行下一个的比较,LIS不变,最后作为LIS的长度并返回


例如:
首先我们在主方法里面创建一个数组: 这里写图片描述
然后我们再创建一个方法函数:lis(int[] arr,int n) 这里写图片描述
其中: arr是我们已经创建好的数组,n是数组的长度


接下来写我们函数里面的代码,我们在lis函数里面创建一个lisArr数组 记忆我们用来比较数值的数量
这里写图片描述

定义循环变量i,j 以及最大值MAX, 这里写图片描述其中i,j用于循环,也就是用于arr数组索引对数组里面的值进行比较的索引变量,MAX是得到算好的LIS数组里面的最大数值,在写代码前我们必须要了解两点,第一:重叠子问题,第二,最优子结构

1)重叠子问题:
考虑到上面的实现,以下是大小为4的数组的递归树。lis(n)给出了arr []的LIS长度。

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

我们可以看到,有很多问题一次又一次得到解决。因此,此问题具有重叠子结构属性,可以通过使用Memoization或Tabulation来避免相同子问题的重新计算。以下是LIS问题的一个列表实现。

2)最优子结构:给定问题具有最优子结构性质,如果给定问题的最优解可以通过使用子问题的最优解得到。
例如,最短路径问题具有以下最佳子结构属性:
如果节点x位于从源节点u到目的节点v的最短路径,则从u到v的最短路径是从u到x的最短路径和最短路径从x到v的路径。像Floyd-Warshall和Bellman-Ford这样的标准的所有对最短路径算法都是动态规划的典型例子。
另一方面,最长路径问题没有最佳子结构属性。这里的“最长路径”是指两个节点之间最长的简单路径(没有周期的路径)。考虑CLRS书中给出的以下未加权图。从q到t有两条最长的路径:q→r→t和q→s→t。与最短路径不同,这些最长的路径不具有最佳的子结构属性。例如,最长路径q→r→t不是从q到r的最长路径和从r到t的最长路径的组合,因为从q到r的最长路径是q→s→t→r,最长路径从r到t是r→q→s→t。这里写图片描述

详细代码如下

static int lis(int arr[],int n) {
    int[] lis = new int[n];
    int i,j,MAX = 0;

    for (i = 0; i < lis.length; i++) {
        lis[i] = 1;
    }
    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;
            }
        }
    }
    //找到LIS最大值返回
    for (i = 0;  i < lis.length; i++) {
        if(MAX < lis[i]) {
            MAX = lis[i];
        }
    }
    return MAX;
}

简单对这代码讲解一下

    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;
                }
            }
        }

Arr[i] > arr[j] = 22 > 10 后面那个数大于前面那个数 我们则在Lis数组里面给下标为i的变量加1赋值,1+1=2 以此类推下去,发现大于当前的数,则继续+1操作,当作最长子序列的计数 22 > 10 ? yes 则 Lis[i] = Lis[j]+1 否则i继续循环下一个做比较,最后就得出Lis的最大值了。

输出结果:这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值