
时间复杂度:
O(nlogn)
//单调栈问题
//分别计算从左向右和从右向左的最长上升子序列,分别存储到两个数组中
import java.util.*;
class Main{
static int n = 0, N = 1010;
static int[] nums = new int[N];
static int[] left = new int[N], right = new int[N];
static int bs(int[] max, int len, int num){//找到从左到右第一个大于num的数字
int l = 0, r = len;
while(l < r){
int mid = l + r >> 1;//+1防止mid不变造成死循环。
if(max[mid] < num)l = mid + 1;
else r = mid;
}
return l;
}
public static void main(String[] args)throws Exception{
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
for(int i = 1; i <= m; ++i)nums[i] = sc.nextInt();
int[] st = new int[N];//单调栈
int tt = -1;
for(int i = 1; i <= m; ++i){
if(tt == -1)st[++tt] = nums[i];
if(tt >= 0 && st[tt] > nums[i]){
int index = bs(st, tt, nums[i]);
st[index] = nums[i];
}
if(st[tt] < nums[i])st[++tt] = nums[i];
left[i] = tt + 1;
}
tt = -1;
for(int i = m; i >= 1; --i){
if(tt == -1)st[++tt] = nums[i];
if(tt >= 0 && st[tt] > nums[i]){
int index = bs(st, tt, nums[i]);
st[index] = nums[i];
}
if(st[tt] < nums[i])st[++tt] = nums[i];
right[i] = tt + 1;
}
int max = 0;
for(int i = 1; i <= m; ++i){
max = Math.max(max, left[i] + right[i] - 1);
}
System.out.print(max);
}
}
本文介绍了一种使用单调栈解决最长上升子序列问题的方法,通过分别计算从左向右和从右向左的最长上升子序列,最终找出整个序列中的最长上升子序列长度。时间复杂度为O(nlogn),适用于需要高效处理此类问题的场景。
364

被折叠的 条评论
为什么被折叠?



