300. 最长递增子序列
题目链接:300. 最长递增子序列
方法:动态规划
解题思路
- 状态表示:\(dp[]\)
- 集合:表示以 \(i\) 结尾的所有递增子序列;
- 属性:\(dp[i]\) 表示集合中最长子序列的长度。
 
- 状态计算:
- 集合划分:枚举以 \(i\) 结尾的所有递增子序列的其前一个元素可能的下标 [0, i - 1],将其划分为以 \(i\) 结尾的所有递增子序列中前一个元素是 \(j\)的集合,\(0 <= j <= i - 1, nums[j] < nums[i]\)。
- \(dp[i] = max\{dp[j] + 1, 1\}\)
 
代码
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        int dp[n]; memset(dp, 0, sizeof(dp));
        dp[0] = 1;
        int ans = 1;
        for (int i = 1; i < n; i ++ ) {
            dp[i] = 1;
            for (int j = 0; j < i; j ++ ) {
                if (nums[i] > nums[j]) {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
            ans = max(ans, dp[i]);
        }
        return ans;
    }
};
优化解法:单调 + 二分
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        int ans = 0, q[n + 1]; memset(q, 0, sizeof(q));
        q[0] = -2e9;
        for (int i = 0; i < n; i ++ ) {
            int l = 0, r = ans;
            while (l < r) {
                int mid = l + r + 1 >> 1;
                if (q[mid] < nums[i]) l = mid;
                else r = mid - 1;
            }
            ans = max(ans, r + 1);
            q[r + 1] = nums[i];
        }
        return ans;
    }
};
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        int ans = 0, q[n + 1]; memset(q, 0, sizeof(q));
        q[0] = -2e9;
        for (int i = 0; i < n; i ++ ) {
            int idx = lower_bound(q, q + ans + 1, nums[i]) - q;
            ans = max(ans, idx);
            q[idx] = nums[i];
        }
        return ans;
    }
};
复杂度分析
时间复杂度:\(dp\)—\(O(n^2)\),优化—\(O(nlogn)\);
空间复杂度:\(O(n)\)。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号