输出两行,第一行包括一个正整数n(n<=100000),代表数组长度。第二行包括n个整数,代表数组arr。
输出一行。代表你求出的最长的递增子序列。
9 2 1 5 3 6 4 8 9 7
1 3 4 8 9
5 1 2 8 6 4
1 2 4
其最长递增子序列有3个,(1,2,8)、(1,2,6)、(1,2,4)其中第三个字典序最小,故答案为(1,2,4)
时间复杂度,空间复杂度
。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] strArr = br.readLine().split(" ");
int[] arr = new int[n];
for(int i = 0; i < n; i++){
arr[i] = Integer.parseInt(strArr[i]);
}
int[] dp = new int[n];
int[] ends = new int[n];
dp[0] = 1;
ends[0] = arr[0];
int tail = 0; // 有效区域末尾
int maxLen = 1, maxIdx = 0; // 最长递增子序列长度和index
for(int i = 1; i < n; i++){
int index = lowerbound(ends, 0, tail, arr[i]);
dp[i] = index + 1; // 以i结尾的最长递增子序列长度为index+1
ends[index] = arr[i];
if(index > tail){
tail++; // 有效区扩充
}
if(dp[i] >= maxLen){
maxLen = dp[i];
maxIdx = i;
}
}
// 还原字典序最小的最长递增子序列
int[] increasingSeq = new int[maxLen];
for(int i = maxIdx; i >= 0; i--){
// 从后往前更新,遇到递增子序列长度为maxLen的arr[i]就更新结尾位置,然后把maxLen缩短
if(dp[i] == maxLen){
increasingSeq[--maxLen] = arr[i];
}
}
for(int i = 0; i < increasingSeq.length; i++){
System.out.print(increasingSeq[i] + " ");
}
}
private static int lowerbound(int[] arr, int L, int R, int target) {
int left = L, right = R;
int index = R + 1;
while(left <= right){
int mid = left + ((right - left) >> 1);
if(arr[mid] < target){
left = mid + 1;
}else{
index = mid;
right = mid - 1;
}
}
return index;
}
}