题目描述
思路分析
朴素做法是Dp O
(
n
2
)
(n^2)
(n2)
f
[
i
]
:
以
i
结
尾
的
最
长
上
升
子
序
列
的
长
度
f[i]:以i结尾的最长上升子序列的长度
f[i]:以i结尾的最长上升子序列的长度
f
[
i
]
=
m
a
x
(
1
,
f
[
j
]
+
1
)
(
对
所
有
0
<
=
j
<
i
)
f[i]=max(1,f[j]+1) (对所有0<=j<i)
f[i]=max(1,f[j]+1)(对所有0<=j<i)
最优做法是贪心 O
(
n
l
o
g
n
)
(nlogn)
(nlogn)
贪心:开一个数组记录每个长度下的结尾最小值,显然是单调增的。每次二分找到比当前数小的最大的位置,把下一个位置更新为当前数。最后整个数组的长度就是答案。
代码实现
//朴素做法:Dp
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
vector<int> f(n);
f[0]=1;
for(int i=1;i<n;i++){
f[i]=1;
for(int j=0;j<i;j++){
if(nums[j]<nums[i]) f[i]=max(f[i],f[j]+1);
}
}
int res=0;
for(int i=0;i<n;i++) res=max(res,f[i]);
return res;
}
};
//最优做法:贪心
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
vector<int> q;
for(auto x:nums){
if(q.empty()||x>q.back()) q.push_back(x);
else {
if(x<=q[0]) q[0]=x;
else{
int l=0,r=q.size()-1;
while(l<r){
int mid=r+l+1>>1;
if(q[mid]<x) l=mid;
else r=mid-1;
}
q[l+1]=x;
}
}
}
return q.size();
}
};