LeetCode300. Longest Increasing Subsequence

题目链接:

https://leetcode.com/problems/longest-increasing-subsequence/

题目描述:

求最长增长子序列包含数字个数。

Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4.

思路:

方法1:
时间复杂度O(n^2)。
dp[i]记录以nums[i]为结尾的最长增长子序列长度。
序列长度由1扩展到n。

如果最长增长子序列以nums[i]结尾,那么在nums[0..i-1]中所有比nums[i]小的数都可以作为倒数第二个数。在这么多倒数第二个数的选择中,以哪个数结尾的最长增长子序列更大,就选那个数作为倒数第二个数。
所以有dp[i]=max(dp[i],dp[j]+1);(j < i)

方法2:
时间复杂度O(nlogn)。
数组ends[0..right]。
ends[j]记录长度为j+1时的增长子序列的最小结尾元素。
ritgh代表当前最长增长子序列的长度-1。
初始化时ends[0]=nums[0],right=0。
序列长度由1到n扩展(相当于i由1遍历到n-1,不断新加入元素nums[i],看是否满足条件来判断是否增加最长增长子序列的长度)。每当新加入元素nums[i],就在ends[0..right]数组里面找,看是否有大于等于nums[i]的数,如果有,把最左边的大于或等于nums[i]的数,假设数字为ends[b],把ends[b]更新为nums[i],right不变。但是如果没有,那么证明此时的最长增长子序列长度又可以增加来,ritgh=right+1,ends[right]=nums[i]。
查找ends最左边的大于或等于nums[i]的数,可以用二分查找优化。

代码:

//方法1:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int len=nums.size();
        if(len==0){
            return 0;
        }
        vector<int> dp(len,1);
        int longest=1;
        for(int i=1;i<len;i++){
            for(int j=0;j<i;j++){
                if(nums[j]<nums[i]){
                    dp[i]=max(dp[i],dp[j]+1);
                }
            }
            longest=max(longest,dp[i]);
        }
        return longest;
    }
};

22 / 22 test cases passed.

Status: Accepted

Runtime: 116 ms  


//方法2:
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
if(n==0){
return 0;
}
vector<int> ends(n);
ends[0]=nums[0];
int right=0;
int low,high,mid;
int longest=1;
for(int i=1;i<n;i++){
low=0;
high=right;
while(low<=high){
mid=(high+low)/2;
if(nums[i]>ends[mid]){
low=mid+1;
}
else{
high=mid-1;
}
}
right=max(right,low);
ends[low]=nums[i];
}
return right+1;
}
};
  

你可能感兴趣的:(LeetCode,动态规划)