最优解-最长递增子序列

问题描述

在一个给定的数值序列中,找到一个子序列,使得这个子序列元素的数值依次递增,并且这个子序列的长度尽可能地大。最长递增子序列中的元素在原序列中不一定是连续的。

动态规划的逻辑,借助高中数学的归纳法,我们先假设这个结论在 k<n 时成立,然后根据这个假设,想办法推导证明出 k=n 的时候此结论也成立。如果能够证明出来,那么就说明这个结论对于 k 等于任何数都成立。

步骤

定义数组array
定义数组dp,dp[i] 表示以 array[i] 这个数结尾的最长递增子序列的长度。dp[i] 初始值为 1,因为以 array[i] 结尾的最长递增子序列起码要包含它自己。
假设我们已经知道了 dp[0…i] 的所有结果,我们如何通过这些已知结果推出 dp[i+1] 呢?
动态规划的核心:array[i+1] = k,既然是递增子序列,我们只要找到前面那些结尾比k小的子序列,然后把 k 接到最后,就可以形成一个新的递增子序列,而且这个新的子序列长度加一
比如数组:1,4,3,4,2。
对应的
dp[0]=1;
dp[1]=2;
dp[2]=2;
dp[3]=3;
dp[4]=2
如果在后面增加一个数3。则数组变为1,4,3,4,2,3;那么dp[5]怎么算呢?找到比3小的数字对应的dp[i]最大值(也就是最长),然后+1,就是dp[5]的值。也就是array[4]=2的值小于3,且dp[4]=2最长。

package com.algorithm;

import java.util.Arrays;

/**
 * long increasing subseq
 */
public class LIS {

        public static void main(String[] args) {
            Integer[] array = new Integer[]{1,4,3,4,2,3};
            int[] dp = new int[array.length];
            Arrays.fill(dp,1); //初始化为1
            for(int i = 0; i<array.length;i++) {
                for(int j = 0; j<i;j++) {
                    if(array[j] < array[i]) {
                        //找到了当前的值array[i]比array[0..j]小
                        dp[i] = Math.max(dp[i],dp[j]+1);//取dp值最大,也就是最长的序列
                    }
                }
            }
            //输出最长子序列的长度
            int res = 0;
            for (int i = 0; i < dp.length; i++) {
                res = Math.max(res, dp[i]);
            }
            System.out.println("long increasing subseq:"+res);
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值