给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)
例如:给定一个长度为8的数组A{1,3,5,2,4,6,7,8},则其最长的单调递增子序列为{1,2,4,6,7,8},长度为6.
输入描述:
第一行包含一个整数T,代表测试数据组数。
对于每组测试数据:
N-数组的长度
a1 a2 … an (需要计算的数组)
保证:
1<=N<=3000,0<=ai<=MAX_INT.
输出描述:
对于每组数据,输出一个整数,代表最长递增子序列的长度。
输入例子:
2
7
89 256 78 1 46 78 8
5
6 4 8 2 17
输出例子:
3
3
/**
* 维护一个数组MaxV[i],记录长度为i的递增子序列中最大元素的最小值,
* 并对于数组中的每个元素考察其是哪个子序列的最大元素,二分更新MaxV数组,
* 最终i的值便是最长递增子序列的长度。
*/
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int t = scan.nextInt();
int n;
while (--t >= 0) {
n = scan.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = scan.nextInt();
}
System.out.println(LIS(arr,n));
}
scan.close();
}
private static int LIS(int[] arr, int n) {
int[] maxValue = new int[n];
maxValue[0] = arr[0];
int len = 1;
for (int i = 1; i < n; i++) {
if (arr[i] > maxValue[len - 1]) {
maxValue[len++] = arr[i];
}else {
int index = binarySearch(maxValue,len,arr[i]);
maxValue[index] = arr[i];
}
}
return len;
}
private static int binarySearch(int[] maxValue, int len, int x) {
int left = 0;
int right = len - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (maxValue[mid] < x) {
left = mid + 1;
}else if (maxValue[mid] > x){
right = mid -1;
}else {
return mid;
}
}
return left;
}
}