DP3 最长上升子序列 LIS @geeksforgeeks

Let us discuss Longest Increasing Subsequence (LIS) problem as an example problem that can be solved using Dynamic Programming.
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}.

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.

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.


package DP;

import java.util.Arrays;	

// 最长递增子序列-Longest Increasing Subsequence
/**
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

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

http://www.geeksforgeeks.org/dynamic-programming-set-3-longest-increasing-subsequence/
 */
public class LIS {

	public static void main(String[] args) {
		int[] A = {10, 22, 9, 33, 21, 50, 41, 60};
		System.out.println(lis(A));
		System.out.println(lis(A, A.length));
	}
	
	/* 
	  A Naive recursive implementation of LIS problem 
	 	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
	*/
	public static int _lis(int arr[], int n, int[] maxRef){
		if(n == 1){		/* Base case */
			return 1;
		}
		int res, maxEndingHere = 1;	// length of LIS ending with arr[n-1]
		 /* Recursively get all LIS ending with arr[0], arr[1] ... ar[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, maxRef);
			if(arr[i-1] < arr[n-1] && res+1>maxEndingHere){
				maxEndingHere = res + 1;
			}
		}
		// Compare max_ending_here with the overall max. And update the
	    // overall max if needed
		if(maxRef[0] < maxEndingHere){
			maxRef[0] = maxEndingHere;
		}
		// Return length of LIS ending with arr[n-1]
		return maxEndingHere;
	}
	
	public static int lis(int arr[], int n){
		int[] max = {1};
		_lis(arr, n, max);
		return max[0];
	}
	
	
	
	//==========================================

	// 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
		
		int max = Integer.MIN_VALUE;
		
		// 对每一个数字求其LIS
		for(int i=1; i<A.length; i++){
			// 找出A[i]能接在哪些数字后面,
			// 如果可以接,找出接完后长度最大那个
			for(int j=0; j<i; j++){
				if(A[j]<A[i]){		// 只有符合递增规律的才能接
					// 找出接完后长度最大那个
					dp[i] = Math.max(dp[i], dp[j]+1);
					max = Math.max(max, dp[i]);
				}
			}
		}
		return max;
	}

	
	
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值