最长上升子序列的长度

1)第一种思路是每次确认当点元素为终节点的时候,由已经其他情况推出自己的情况

/**
 * 最大上升子序列的长度
 * 给定一个无序的序列,求其最大上升子序列的最大长度
 * 子序列要为上升并且长度最长
 * 思路:
 * 序列一共k个点,{a1, a2, ..., ak} 以每个点为终点,这样就有k个状态,分别讨论它们的最长上升子序列,然后取最大的情况
 * 维护一个一维数组maxLen[k],表示以序列元素{ak}为终点时的最长上升子序列
 * 递推公式:
 * maxLen[1] = {ak}
 * maxLen[k] = Max{maxLen[i]} + 1(i为k左边的元素,并且ai小于ak,在这些元素中挑选出以该元素为终点,上升子序列最长的情况,加上{ak}自己,就是以{ak}为
 * 终点的最长上升子序列)
 */
package dp;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
	static int[] a = null;
	static int[] maxLen = null;
	public static void main(String[] args){
		/**
		 * 输入
		 * 第一行:n 表示序列的长度
		 * 第二行:长度为n的序列,元素之间空格隔开
		 * 输出:
		 * 最长上升子序列的长度
		 * 测试结果:
		 * 输入:
		 *  7
			1 7 3 5 9 4 8
			输出:
			4
		 */
		//代码实现
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		a = new int[n+1];
		maxLen = new int[n+1];
		maxLen[1] = 1;//初始化边界条件
		for(int i = 1; i <= n; i++){
			a[i] = in.nextInt();
		}
		//分别讨论序列的每个节点为终点的情况,每个子序列的最长上升子序列的长度,维护在对应的maxlen[i]数组里
		for(int i = 1; i <=n; i++){
			//针对于{ai},其左边的并且小于{ai}的所有元素中分别为中节点,最大的上升子序列长度
			for(int j = 1; j < i; j++){
				if(a[j] < a[i]){
					//满足情况的左边子序列的终节点,每次都尝试更新{ai}的最长子序列长度
					maxLen[i] = Math.max(maxLen[i], maxLen[j]+1);
				}
			}
		}
		//循环完了之后,一维数组maxLen[i]即已经维护完了,我们已经分别求出以{ak}为终点的最长子序列长度,以最后一个元素为
		//终点的最长上升子序列就是问题的结果
		System.out.println(maxLen[n]);
	}
}


2)第二种思路是已知当前元素为终点的最长上升子序列的长度,然后去更新每一个与自己有关的最长上升子序列的长度

/**
 * 最大上升子序列的长度
 * 给定一个无序的序列,求其最大上升子序列的最大长度
 * 子序列要为上升并且长度最长
 * 思路:
 * 序列一共k个点,{a1, a2, ..., ak} 以每个点为终点,这样就有k个状态,分别讨论它们的最长上升子序列,然后取最大的情况
 * 维护一个一维数组maxLen[k],表示以序列元素{ak}为终点时的最长上升子序列
 * 递推公式:
 * maxLen[1] = {ak}
 * maxLen[k] = Max{maxLen[i]} + 1(i为k左边的元素,并且ai小于ak,在这些元素中挑选出以该元素为终点,上升子序列最长的情况,加上{ak}自己,就是以{ak}为
 * 终点的最长上升子序列)
 */
package dp;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
	static int[] a = null;
	static int[] maxLen = null;
	public static void main(String[] args){
		/**
		 * 输入
		 * 第一行:n 表示序列的长度
		 * 第二行:长度为n的序列,元素之间空格隔开
		 * 输出:
		 * 最长上升子序列的长度
		 * 测试结果:
		 * 输入:
		 *  7
			1 7 3 5 9 4 8
			输出:
			4
		 */
		//代码实现
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		a = new int[n+1];
		maxLen = new int[n+1];
		maxLen[1] = 1;//初始化边界条件
		for(int i = 1; i <= n; i++){
			a[i] = in.nextInt();
		}
		//分别讨论序列的每个节点为终点的情况,每个子序列的最长上升子序列的长度,维护在对应的maxlen[i]数组里
		for(int i = 1; i <=n; i++){
			//针对于{ai},当自己的最长子序列确定是时候,尝试着去更新它右边的所有比它大的元素为终结的最长上升子序列长度
			for(int j = i+1; j <= n; j++){
				if(a[j] > a[i]){
					//满足情况的右边子序列的终节点,每次都尝试更新{aj}的最长子序列长度
					maxLen[j] = Math.max(maxLen[j], maxLen[i]+1);
				}
			}
		}
		//循环完了之后,一维数组maxLen[i]即已经维护完了,我们已经分别求出以{ak}为终点的最长子序列长度,以最后一个元素为
		//终点的最长上升子序列就是问题的结果
		System.out.println(maxLen[n]);
	}
}


你可能感兴趣的:(编程题)