动态规划的经典题!
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

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

被折叠的 条评论
为什么被折叠?



