给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int len = nums.size();
if(len <= 0)
return 0;
vector<int> dp(2500, 1);
// dp[i]的意思是:包含nums[i]的前面i+1个结点的最长子序列
dp[0] = 1;
int maxlen = 1;
for(int i = 1; i < len; i++) {
for(int j = 0; j < i; j++) {
if(nums[i] > nums[j]) {
dp[i] = max(dp[i], dp[j] + 1);
if(dp[i] > maxlen)
maxlen = dp[i];
}
}
}
return maxlen;
}
};
越小的数字越要往前放,让坡度越缓慢
复杂度:时间复杂度O(nlogn)
class Solution {
public:
int lengthOfLIS(vector& nums) {
//让坡度上升尽可能缓慢
int len = nums.size();
if(len <=0) return 0;
vector v;
v.push_back(nums[0]);
for(int i = 1; i < len; i++) {
if(nums[i] > v[v.size()-1]) {
v.push_back(nums[i]);
} else if (nums[i] < v[v.size()-1]) {
//二分查找,找到比该数字大或者相等的第一个位置,然后放进去
int left = 0;
int right = v.size()-1;
int mid;
while(left < right) {
mid = (left + right)/2;
if(v[mid] == nums[i]) {
left = mid;
break;
} else if (v[mid] > nums[i]) {
right = mid;
} else {
left = mid + 1;
}
}
v[left] = nums[i];
}
}
return v.size();
}
};
0 1 2 3 4 5
0 1 0 3 2 3
i = 0:
v = 0
i = 1
v = 0 1
i = 2
le = 0 ri = 1 mid = 0
v[0] == 0
le = 0
v = 0 1
i = 3
v = 0 1 3
i = 4 放2
le = 0 ri = 2 mid = 1
v[1] = 1 < 2
le = 2 ri = 2
v = 0 1 2
i = 5
v = 0 1 2 3