package cn.edu.hit;
import java.util.Scanner;
/**
* 求最长单调序列
* @author admin
*
*/
public class LongestMonotone {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();//数组的长度
int[] array = new int[n];
for (int i = 0; i < n; i++) {
array[i] = in.nextInt();
}
int[] count = new int[n];//用于记录到达每个位置的最长子序列
int[] record = new int[n];//记录达到某个位置的最大序列的前一个位置
for (int i = 0; i < record.length; i++) {
record[i] = -1;
}
//n^2实现
// for (int i = 0; i < array.length-1; i++) {
// for (int j = i; j > -1; j--) {
// if(array[i+1]>array[j]){//加个等号就是最长不下降序列
// //count[i+1] = Math.max(count[i+1], count[j]+1);
// if(count[i+1] < count[j]+1){
// count[i+1] = count[j]+1;
// record[i+1] = j;//记录前一个位置
// }
// }
// }
// }
// int max = count[0],index = 0;
// for (int i = 0; i < count.length; i++) {//求出最长的序列长度
// if(max < count[i]){
// max = count[i];
// index = i;
// }
// }
// System.out.println(max+1);
// //输出最长子序列
// int[] record1 = new int[n];//正序记录最长子序列
// int num = 0;
// record1[num] = array[index];//记录最后一个
// while(record[index]!=-1){
// num++;
// record1[num] = array[record[index]];
// index = record[index];
// }
// for (int i = num; i > -1; i--) {
// System.out.print(record1[i] + " ");
// }
//nlogn实现:关键是第二个循环要和所有的小于i的j去比较,倘若一开始就保存了各个最长子序列位置的最大值,再将新出现的值进行二分查找,确定位置即可
int[] len = new int[n];
for (int i = 0; i < len.length; i++) {//初始化要将其初始化为无穷大
len[i] = Integer.MAX_VALUE;
}
int max1 = 0;
for (int i = 0; i < array.length; i++) {
int pos = bfind(0, i, array[i], len);
len[pos] = Math.min(len[pos], array[i]);//选取一个小的元素
count[i] = pos;//记录每个位置最长子序列的长度
max1 = Math.max(max1, count[i]);
}
System.out.println(max1+1);
}
//二分查找位置
public static int bfind(int first,int last,int value,int[] len){
int mid;
while(first<=last){
mid = (first+last)/2;
if(len[mid]<value){
first = mid + 1;
}else if(len[mid]>value){
last = mid-1;
}else{
return mid;
}
}
return first;
}
}
最长不下降子序列
最新推荐文章于 2023-07-02 22:29:10 发布