问题:
从一列不重复的数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的。
Input :
输入第一行为用例个数, 每个测试用例输入是一个数组,数值通过空格隔开。
Output:
输出筛选之后的数组,用空格隔开。如果有多种结果,则一行一种结果, 单个输入的所有结果按从小到大排序,排序的key的优先级随index递增而递减 例如 3 4 7 6; 1 3 7 5; 1 2 7 6; 1 3 7 6 排序成 1 2 7 6;1 3 7 5;1 3 7 6; 3 4 7 6;
Sample Input :
4 1 2 4 7 11 10 9 15 3 5 8 6 1 3 5 4 7 6 4 5 3 1 2 3 3 2 1
Sample Output:
1 2 4 7 11 10 9 8 6 1 3 4 7 6 4 3 1 3 4 7 6 5 3 1 3 5 7 6 4 3 1 3 5 7 6 5 3 1 2 3 3 2 1
解题思路:
最长序列长度:
首先求数组从左到右,以 i 结尾的最长递增子序列 LIS,再求数组从右到左,以 i 结尾的最长递增子序列 LDS,对每个位置的 i ,序列的最长长度为 LIS[i] + LDS[i] - 1 ,求出最长序列长度。
输出每个序列结果:
对每个位置的序列长度进行遍历,将每个最大序列长度 i 的位置 记录到 maxIndex中。再对maxIndex中每个位置进行遍历,分别求出列表中该元素的前缀和后缀,组成一组答案,最终遍历完成,对答案进行去重,排序,输出。
求前缀与后缀过程:
假设列表为arr,当前maxIndex = i , 则前缀最长上升子序列长度为front = 1、2、3、...、LIS[i] - 1,对这些长度倒序遍历,找出列表中 i 之前满足LIS[j] = front的位置 j,将同一 front 下的所有满足条件的位置 j 放入列表中,后对当前结果序列进行遍历,如最初结果序列中只有 11 一个元素,取得结果序列中首部的元素,如"7 11"的结果序列中,首部元素first_num = 7,若arr[j] < first 并且 j < arr.indexof(7),即当前位置的元素比结果序列中首部元素要小,并且该元素的索引,在首部元素索引的前面,则,string = arr[j] + " " + string,即将当前位置的元素加入到结果序列中。不断循环,直至求出所有前缀。
求后缀的过程与求前缀的过程基本类似。
参考代码(JAVA):
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class Main5 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int cases = Integer.parseInt(sc.nextLine());
for(int i = 0; i < cases ; i++) {
String str1 = sc.nextLine();
String[] str3 = str1.split(" ");
int n = str3.length;
ArrayList<Integer> arr = new ArrayList<Integer>();
for(int j = 0; j < str3.length; j++){
arr.add(Integer.parseInt(str3[j]));
}
int[] LIS = getLIS(arr,n);
int[] LDS = getLDS(arr,n);
ArrayList<Integer> maxIndex = new ArrayList<Integer>();
int[] lengthArr = getLengthAndMaxLength(LIS,LDS,n);
int maxLength = lengthArr[lengthArr.length-1];
for (int j = 0; j < n; j++) {
if(lengthArr[j] == maxLength) {
maxIndex.add(j);
}
}
// System.out.println(maxLength);
ArrayList<String> output = getOutPut(arr,lengthArr,n,maxIndex,LIS,LDS);
output = getUniqueOutput(output);
for (String string : output) {
System.out.println(string);
}
}
}
private static ArrayList<String> getUniqueOutput(List<String> output) {
// TODO Auto-generated method stub
Set<String> s = new HashSet<>();
s.addAll(output);
ArrayList<String> unique = new ArrayList<String>();
unique.addAll(s);
Collections.sort(unique);
return unique;
}
private static ArrayList<String> getOutPut(ArrayList<Integer> arr, int[] lengthArr, int n,
ArrayList<Integer> maxIndex, int[] LIS, int[] LDS) {
ArrayList<String> output = new ArrayList<String>();
for (Integer i : maxIndex) {
int front = LIS[i] - 1;
ArrayList<String> sFront = new ArrayList<String>();
sFront.add(arr.get(i)+"");
while(front > 0) {
ArrayList<Integer> index = new ArrayList<Integer>();
for (int j = 0; j < i; j++) {
if(LIS[j] == front) {
index.add(j);
}
}
if(!index.isEmpty()) {
sFront = addFirst(sFront,arr,index);
}
front--;
}
int after = LDS[i] - 1;
while(after > 0) {
ArrayList<Integer> index = new ArrayList<Integer>();
for (int j = i + 1; j < n; j++) {
if(LDS[j] == after) {
index.add(j);
}
}
if(!index.isEmpty()) {
sFront = addAfter(sFront,arr,index);
}
after--;
}
output.addAll(sFront);
}
return output;
}
private static ArrayList<String> addAfter(ArrayList<String> str,
ArrayList<Integer> arr, ArrayList<Integer> pos) {
ArrayList<String> s = new ArrayList<String>();
for (Integer index : pos) {
if(!str.isEmpty()) {
for (String string : str) {
int last_num = Integer.parseInt(string.split(" ")[string.split(" ").length - 1]);
if(arr.get(index) < last_num && index > arr.lastIndexOf(last_num)) {
string = string + " " + arr.get(index);
s.add(string);
}
}
}else {
s.add(arr.get(index)+"");
}
}
return s;
}
private static ArrayList<String> addFirst(ArrayList<String> str, ArrayList<Integer> arr, ArrayList<Integer> pos) {
ArrayList<String> s = new ArrayList<String>();
for (Integer index : pos) {
if(!str.isEmpty()) {
for (String string : str) {
int first_num = Integer.parseInt(string.split(" ")[0]);
// System.out.println(first_num +" "+ arr.indexOf(first_num));
if(arr.get(index) < first_num && index < arr.indexOf(first_num)) {
string = arr.get(index) + " " + string;
s.add(string);
}
}
}else {
s.add(arr.get(index) + "");
}
}
return s;
}
private static int[] getLengthAndMaxLength(int[] LIS,int[] LDS,int n) {
int maxLength = 0;
int[] lengthArr = new int[n + 10];
for (int j = 0; j < n; j++) {
int length = LIS[j] + LDS[j] - 1;
lengthArr[j] = length;
if(length > maxLength) {
maxLength = length;
}
}
lengthArr[lengthArr.length - 1] = maxLength;
return lengthArr;
}
//获取以0为起点,以i为终点的最长递增子序列
public static int[] getLIS(ArrayList<Integer> arr, int n) {
int[] LIS = new int[n+10];
Arrays.fill(LIS, 1);
for (int i = 1; i < arr.size(); i++) {
for (int j = 0; j < i; j++) {
if(arr.get(j) < arr.get(i)) {
LIS[i] = Math.max(LIS[i], LIS[j] + 1);
}
}
}
return LIS;
}
//获取以i为起点,以n为终点的最长递减子序列
public static int[] getLDS(ArrayList<Integer> arr, int n) {
int[] LDS = new int[n+10];
Arrays.fill(LDS, 1);
for (int i = n - 2; i >= 0; i--) {
for (int j = i + 1; j < n; j++) {
if(arr.get(j) < arr.get(i)) {
LDS[i] = Math.max(LDS[i], LDS[j] + 1);
}
}
}
return LDS;
}
}
如有错误,请指正。