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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值