300. Longest Increasing Subsequence 最长递增子序列
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18]
,
The longest increasing subsequence is [2, 3, 7, 101]
, therefore the length is 4
. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
dp[i]=max(dp[j])+1,∀0≤j<i
LISlength=max(dp[i]),∀0≤i<n
dp[i]保存当前节点结尾的最长子序列的长度。对于每一个当前节点,遍历之前的节点,当前节点大于前面的节点时,取前面的节点加一,遍历一遍之后的最大值就是以
当前节点结尾的最长递增子序列
每次内循环都与当前保存的最大值比较,最终返回最大值 O(n2)
class Solution {
public:
int lengthOfLIS(vector& nums) {
int n=nums.size();
if(!n) return 0;
vector dp(n,0);
int res=1;
dp[0]=1;
for(int i=1;inums[j])
{
maxsas=max(maxsas,dp[j]);
}
}
dp[i]=maxsas+1;
res=max(res,dp[i]);
}
return res;
}
};
二分查找:
也是建立一个矩阵。这个矩阵不是以当前元素结尾的最大长度。而是满足当前最长子序列长度的最小结尾数。比如res[i]=c,指的是,长为i+1的最长子序列的结尾最小是c。
这种方法做的优化是,假如遍历到了i位置,res到了j位置,意思是,目前从0到i位置的最长子序列是j+1,这个最长子序列的结尾最小是res[j]。而这种res一定是递增的,长度为2的结尾最小值不可能比长度为三的结尾最小值大。加入长度为2的结尾最小值是6,那么在当前已扩展区域中,再去找一个数行程长度为三的子序列,这个书一定大于6.
因此,如果在遍历到i+1位置时的数x,在res中二分查找第一个比他大的数y,y之前的数为z。那么x大于z,这说明,从x位置往前看,能找到z比他小,那么x结尾的子序列是x位置序列加一,而y代表的就是这种长度子序列的最小结尾数,所以把y替换成x。
如果二分查找找不到这样的数,说明当前x比现在已知的所有长度的结尾值都大,x可以和最长的那个子序列构成一个更长的子序列。这个时候扩展res数组。
C++中的lower_bound就是查找第一个大于等于查找值的数。有关C++查找的知识参考:
lower_bound()返回值
STL之二分查找 (Binary search in STL)
代码如下:
class Solution {
public:
int lengthOfLIS(vector& nums) {
vector res;//res[i]表示长度为i+1的子序列的结尾是res[i]
for(int i=0;i
类似题目:
354. Russian Doll Envelopes 类似最长递增子序列
646. Maximum Length of Pair Chain 类似与最长子序列但是有简单做法 贪心方法 这道题题意类似,但是可以用贪心解答
求出所有的递增子序列 491334. Increasing Triplet Subsequence 题意类似,方法无关,巧方法