题目来源:https://leetcode.cn/problems/longest-increasing-subsequence/description/
C++题解1:动态规划
用两个循环,每到一个元素,就找它之前的最长递增子序列。
dp[i]表示第i个元素的最长递增子序列,里层遍历寻找之前的最长的递增子序列然后更新dp[i]。
class Solution {
public:int lengthOfLIS(vector<int>& nums) {int n = nums.size();if(n == 1) return 1;int len = 0;vector<int> dp(n, 1); // 前i个最长递增子序列for(int i = 1; i < n; i++){for(int j = 0; j < i; j++) {if(nums[j] < nums[i]) dp[i] = max(dp[i], dp[j] + 1);}len = max(len, dp[i]);}return len;}
};
C++题解2:时间复杂度降低到 O(n log(n))
。应该是贪心+二分查找
对于[10,9,2,5,7,3,101,18],[10]->[9]->[2]->[2,5]->[2,5,7]->[2,3,7](这一步是更新了3的位置,但是最长递增子序列的长度还是为3)->[2,3,7,101]->[2,3,7,18]
class Solution {
public:int lengthOfLIS(vector<int>& nums) {int n = nums.size();if(n == 1) return 1;vector<int> zi(1, 0);zi[0] = nums[0];int len = 1; for(int i = 1; i < n; i++) {if(nums[i] > zi[len-1]) {zi.push_back(nums[i]);len++;}else {int left = 0, right = len-1, mid = floor((left+right)/2);while(left < right) {if(zi[mid] == nums[i]) break;else if(zi[mid] > nums[i]) {right = mid; mid = floor((left+right)/2);}else {left = mid+1;mid = floor((left+right)/2);}}zi[mid] = nums[i];}}return zi.size();}
};