最长递增子序列-Longest Increasing Subsequence

本文探讨了动态规划解决最长递增子序列问题的三种方法:朴素DP、使用两个变量的优化DP和仅关注后续序列的优化DP。通过实例展示了如何应用这些方法并分析了它们的时间复杂度。

动态规划的经典题!


package DP;

import java.util.Arrays;	

public class LIS {

	public static void main(String[] args) {
		int[] A = {5,3,4,8,6,7};
		System.out.println(lis(A));
		System.out.println(lis2(A));
		System.out.println(lis3(A));
	}

	// Naive O(n2) DP solution
	// 看A[i]能接在哪些数字后面
	public static int lis(int[] A){
		
		int[] dp = new int[A.length];		// 对每一个元素存储它的lis
		Arrays.fill(dp, 1);			// 初始化,每个数字本身就是长度为1的lis
		
		// 对每一个数字求其LIS
		for(int i=1; i<A.length; i++){
			// 找出A[i]能接在哪些数字后面,
			// 如果可以接,找出接完后长度最大那个
			for(int j=i-1; j>=0; j--){
				// 只有符合递增规律的才能接
				if(A[j]<A[i]){
					// 找出接完后长度最大那个
					if(dp[j] +1 > dp[i]){
						dp[i] = dp[j] + 1;
					}
				}
			}
		}
		
		int max = Integer.MIN_VALUE;
		// 现在已经有每个数的LIS,找出最长的那个
		for(int i=0; i<dp.length; i++){
			if(dp[i] > max){
				max = dp[i];
			}
		}
		
		return max;
	}
	
	// Use 2 max
	public static int lis2(int[] A){
		int[] dp = new int[A.length];
		Arrays.fill(dp, 1);
		
		int max = 0;
		for(int i=1; i<A.length; i++){
			for(int j=0; j<i; j++){
				if(A[j] < A[i]){
					// 可以灵活的用max函数代替if比较
					dp[i] = Math.max(dp[i], dp[j]+1);
					max = Math.max(max, dp[i]);
				}
			}
		}
		
		return max;
	}
	
	// 看A[i]后面能接上哪些数字
	public static int lis3(int[] A){
		
		int[] dp = new int[A.length];		// 对每一个元素存储它的lis
		Arrays.fill(dp, 1);			// 初始化,每个数字本身就是长度为1的lis
		
		// 对每一个数字求其LIS
		for(int i=0; i<A.length; i++){
			// 看A[i]后面能接上哪些数字
			// 如果可以接,找出接完后长度最大那个
			for(int j=i+1; j<A.length; j++){
				// 只有符合递增规律的才能接
				if(A[j] > A[i]){
					dp[j] = Math.max(dp[j], dp[i]+1);
				}
			}
		}
		
		int max = Integer.MIN_VALUE;
		// 现在已经有每个数的LIS,找出最长的那个
		for(int i=0; i<dp.length; i++){
			if(dp[i] > max){
				max = dp[i];
			}
		}
		
		return max;
	}
	
	
}

Ref:

http://www.geeksforgeeks.org/dynamic-programming-set-3-longest-increasing-subsequence/

http://www.csie.ntnu.edu.tw/~u91029/LongestIncreasingSubsequence.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值