300最长子序列

题目描述:

给定一个无序的整数数组,找到其中最长上升子序列的长度。

示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4 
解释: 最长的上升子序列是 [2,3,7,101]它的长度是 4
 

说明:

  • 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
  • 你算法的时间复杂度应该为 O(n2) 。

进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

动态规划

动态规划:遍历第i个元素时,如果nums[i]比前面第j个数大,那包含第i个元素的最长
上升子序列一定是包含第j元素的,如果i前面有很多个比nums[i]小的数,那包含i的最
长上升子序列一定是包含前面这些比nums[i]小的某个数,也可能是很多个数,也可能
是全部包含比nums[i]小的数。比如[2,5,3,7]在比较7时,前面的2,5,3都比7小,但
是dp[3]只能是3(2,5,7/2,3,7)。所以这个公式表示就是
dp[i]=max(dp[j])+1;(0<=j<i)。
最后选择dp最大的数就是整个数组最长上升子序列长度。
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int>dp(nums.size(),1);
        if(nums.size()==0)
            return 0;
        int i,j,Max=1;
        for(i=1;i<nums.size();i++)
        {
            for(j=0;j<i;j++)
                if(nums[i]>nums[j])
                    dp[i]=max(dp[i],dp[j]+1);
            Max=max(Max,dp[i]);
        }
        
        return Max;
            
    }
};
class Solution {
    public int lengthOfLIS(int[] nums) {
        if(nums==null||nums.length==0){return 0;}
        int[] dp=new int[nums.length];
        dp[0]=1;
        int maxlen=1;
        
        for(int i=1;i<nums.length;i++){
            int maxval=0;
            for(int j=0;j<i;j++){
                if(nums[i]>nums[j]){
                    maxval=Math.max(dp[j],maxval);
                }//如果前面j都没有比i数小的数,那么包含i的序列只能从i开始,dp[i]=1
            }
            dp[i]=maxval+1;
            maxlen=Math.max(maxlen,dp[i]);//随时更新最大的dp值
        }
        return maxlen;
    }
    
}
点赞