这一题与最长上升子序列非常相似(300. 最长递增子序列)
但是如果纯用dp时间复杂度为O(n2),会超时
//动态规划,时间复杂度为O(n2),超时
class Solution {
public int[] longestObstacleCourseAtEachPosition(int[] obstacles) {
int len = obstacles.length;
int[] dp = new int[len];
dp[0] = 1;
for(int i=1;i<len;i++){
dp[i] = 1;
for(int j=0;j<i;j++){
if(obstacles[j] <= obstacles[i]){
dp[i] = Math.max(dp[i], dp[j]+1);
}
}
}
return dp;
}
}
要用动态规划+二分查找来
class Solution {
public int[] longestObstacleCourseAtEachPosition(int[] obstacles) {
int len = obstacles.length;
//记录长度为 k+1 子序列 的尾部元素值
int[] tails = new int[len];
//记录结果
int[] res = new int[len];
//当前tails数组的长度
int cnt = 0;
for(int i=0;i<len;i++){
int l=0, r = cnt;
int num = obstacles[i];
while(l < r){
int mid = (l+r)>>1;
if(num < tails[mid]){
r = mid;
}
else{
l = mid + 1;
}
}
tails[r] = num;
res[i] = r + 1;
if(r == cnt){
++cnt;
}
}
return res;
}
}
tails[k] 的值代表 长度为 k+1 子序列 的尾部元素值。
例如输入的数据为[5,1,5,5,1,3,4,5,1,4]
则tails数组将会一步一步发生变化
【5】
【1】
【1,5】
【1,5,5】
【1,1,5】
【1,1,3】
【1,1,3,4】
【1,1,3,4,5】
【1,1,1,4,5】
【1,1,1,4,4】
这样时间复杂度就降到O(n*logn)