最长非上升子序列

来源:互联网 发布:淘宝买家恶意大量退货 编辑:程序博客网 时间:2024/05/17 18:03

问题描述:

给定一个序列:X1 X2 X3 X4 X5 X6......Xn,试图找到一个最长的子序列,Xi1 Xi2 Xin,使得i1 < i2 < i3 ...而且Xi1 < Xi2 < Xi3......。

举个例子:48 65 34 29 64 38 89

有一种非常简单的做法,能够非常简单的计算出所要序列的长度,但是无法给出序列。过程如下

48

65

65 34

65 34 29

65 64 29

65 64 38

89 64 38

因此最长非上升子序列长度为3,代码如下:

Java

import java.util.ArrayList;import java.util.List;import java.util.Scanner;public class SubSeqDesc {public static void main(String[] args) {Scanner sin = new Scanner(System.in);List<Integer> maxList = new ArrayList<Integer>(32);int ele = 0;if ((ele = sin.nextInt()) != -1) {maxList.add(ele);while ((ele = sin.nextInt()) != -1) {if (maxList.get(maxList.size() - 1) >= ele) {maxList.add(ele);} else {int i = 0;while (maxList.get(i) >= ele)i++;maxList.set(i, ele);}}System.out.println("the longest subsequence' length is " + maxList.size());} else {System.out.println("no sequence...");}}}

另外有一种动态规划的方法。记opt[i](i = 0...len)表示以array[i]为尾的满足条件的序列,那么最终所要求的序列必定在opt[i]中的最大值,也就是序列最大长度。代码如下:

Java

import java.util.ArrayList;import java.util.List;import java.util.Scanner;public class SubSeqDesc2 {public static void main(String[] args) {Scanner sin = new Scanner(System.in);List<Integer> maxList = new ArrayList<Integer>(32);int ele = 0;while ((ele = sin.nextInt()) != -1) {maxList.add(ele);}int len = maxList.size();if (len == 0) {System.out.println("no sequence...");} else {Integer[] seq = new Integer[len];maxList.toArray(seq);int[] opt = new int[len];opt[0] = 1;for(int i = 1; i < len; i++){opt[i] = 1;for(int j = 0; j < i; j++){if(seq[j] >= seq[i] && opt[j] + 1 > opt[i]){opt[i] = opt[j] + 1;}}}int result = opt[0];for(int i = 1; i < len; i++){if(result < opt[i]){result = opt[i];}}System.out.println("the longest subseq is " + result);}}}

根据第二个做法,可以通过加入新的前向数组来输出一个最长的子序列:

Java

import java.util.ArrayList;import java.util.LinkedList;import java.util.List;import java.util.Scanner;public class SubSeqDesc3 {public static void main(String[] args) {Scanner sin = new Scanner(System.in);List<Integer> maxList = new ArrayList<Integer>(32);int ele = 0;while ((ele = sin.nextInt()) != -1) {maxList.add(ele);}int len = maxList.size();if (len == 0) {System.out.println("no sequence...");} else {Integer[] seq = new Integer[len];int[] previous = new int[len];maxList.toArray(seq);int[] opt = new int[len];opt[0] = 1;previous[0] = -1;for(int i = 1; i < len; i++){opt[i] = 1;previous[i] = -1;for(int j = 0; j < i; j++){if(seq[j] >= seq[i] && opt[j] + 1 > opt[i]){opt[i] = opt[j] + 1;previous[i] = j;}}}int result = 0;for(int i = 1; i < len; i++){if(result < opt[i]){result = i;}}System.out.println("length:" + opt[result]);System.out.print("subsequence:");LinkedList<Integer> stack = new LinkedList<Integer>();do{stack.push(result);result = previous[result];}while(result != -1);while(!stack.isEmpty()){System.out.print(seq[stack.pop()] + " ");}System.out.println();}}}