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


思想

在这里插入图片描述

1、穷举

容易想到,穷举所有可能,1 7 9,1 7 8,1 3 5 9 ,1 3 5 8…

2、动态规划实现

(1)一个数组存储输入数据——aa
(2)一个数据保存到第i位为止,的最大长度——bb
(3)初始bb[1] = 1,因为只有一个数,它本身的长度位1
(4)bb数组第二位,bb[2],如果aa[2]>aa[1],那么bb[2] = bb[1]+1,否则bb[2] = 1
(5)bb数组第三位,bb[3],如果aa[3]>aa[2]>aa[1] 那么bb[3] = bb[2]+1=3,否则如果aa[3]>aa[2] 则bb[3] = bb[2]+1,如果aa[3]>aa[1],则bb[3] = bb[1] +1,如果 aa[3]<aa[2] 且aa[3]<aa[1],bb[3] =1
在这里插入图片描述

(6)可以得出公式,bb[i] =max( bb[j] )+1 j 从1到 i -1,并且aa[i]>aa[j]
在这里插入图片描述
(7)构造最大长度,引入数组pre,pre第i位的含意是,到第 i 位为止,最大长度bb[i]是与第几位加1得来的。例如第五位,bb[5] =4 ,表示到第五位为止,最大长度为4,pre[5] =4 指bb[5]的最大长度4,是第4位加1得到的。
在这里插入图片描述

实现

(1)两层for循环,规划出bb数组
(2)lab 标记最大长度 在哪,方便到时候去构造
(3)利用pre数组,构造出最长增长序列,cc数组保存

import java.util.Scanner;

public final class LIS {
	static int[] aa ;
	static int[] bb ;
	static int[] pre ;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()) {
			int n = sc.nextInt();
			aa = new int[n+1];//第一位  aa[0] 没有使用,下面两个数组同理。
			bb = new int[n+1];
			pre = new int[n+1];
			for (int i = 1; i <= n; i++) {
				aa[i] = sc.nextInt();
			}
			System.out.println(solve());
		}
	}
	private static int solve() {
		int MaxLength,max=0,lab=0;//lab标记第几个  是最大长度
		bb[1] = 1;//bb数组第i位 表示 从第1位到第i位为止,最大长度
		pre[1]=0;//假设到第i位为止,最大长度为3 ,那么pre的第i位为4表示,
		//最大长度2 从第4位来。
		
		for (int i = 2; i < aa.length; i++) {
			MaxLength=0;
			for (int j = i-1; j >= 1; j--) {
				
				if(aa[i]>aa[j]&&bb[j]>MaxLength) {
					MaxLength = bb[j];
					pre[i]=j;//MaxLength 从数组哪个位置
					//得来的,方便之后构造。
				}
			}
			bb[i] = MaxLength+1;
			if(bb[i]>max) {
				max=bb[i];
				lab=i;
			}

		}
		int[] cc = new int[max];//保存构造的数组。
		//构造
		int i=lab;
		int j=max-1;
		while(--lab!=0) {
			cc[j] = aa[i];
			j--;
			i = pre[i];
		}
		//print
		for(int z=1;i<cc.length;i++) {
			System.out.print(cc[i]+" ");
		}
		System.out.println();
		//返回最大长度。
		return max;
		
	}

}

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值