题目描述:
题目:链接
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
示例
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
解题思路:
本题主要采用动态规划的方法:
方法一,遍历的时候,记录以当前点为结尾的最长子序列,dp[i],表示以nums[i]为结尾的最长子序列,而dp[i]的取值为:j 在 0 ~ i范围内满足nums[i] > nume[j] 且 dp[j]是dp[0~i]中最大的,则dp[i] = dp[j]+1
|
方法二:设计dp[j]为,j长度下对应的最小的数值,那么当对数组进行遍历时,对于当前的nums[i],如果dp中元素都比它小,将它插到最后,否则,用它覆盖掉比它大的元素中最小的那个。
C++实现
方法一
public:
int lengthOfLIS(vector<int>& nums) {
int s = nums.size();
vector<int> dp(s,1);
for(int i = 0; i < s; i++){
for(int j = 0; j < i; j++){
if(nums[i] > nums[j]){
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
return *max_element(dp.begin(), dp.end());
}
};
方法二:
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int s = nums.size();
if(s < 2) return s;
vector<int> dp;
dp.push_back(nums[0]);
int l, r;
l = r = 0;
for(int i = 1; i < s; i++){
if(nums[i] > dp.back()){
dp.push_back(nums[i]);
}
else{
l = 0;
r = dp.size() - 1;
int m;
while(l < r){
m = l + (r - l) / 2;
if(dp[m] < nums[i]){
l = m + 1;
}
else{
r = m;
}
}
dp[l] = nums[i];
}
}
return dp.size();
}
};
参考文献: