-
https://leetcode.cn/problems/longest-increasing-subsequence/
-
给你一个整数数组 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 。
示例 2:
输入:nums = [0,1,0,3,2,3]
输出:4
示例 3:
输入:nums = [7,7,7,7,7,7,7]
输出:1
LIS即最长上升子序列,指的是给定一个数列,从中选取一个子序列,使得子序列中的所有元素单调递增,并且满足子序列的长度最长。以下是LIS的动态规划代码实现(时间复杂度为 O ( n 2 ) O(n^2) O(n2)):
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
if (n < 2) {
return n;
}
vector<int> dp(n, 1);
int max_len = dp[0];
for (int i = 1; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (nums[i] > nums[j]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
max_len = max(max_len, dp[i]);
}
return max_len;
}
其中, d p [ i ] dp[i] dp[i] 表示以第 i i i 个元素为结尾的最长上升子序列的长度。状态转移方程为:
d p [ i ] = max j = 0 i − 1 { d p [ j ] + 1 } , if n u m s [ i ] > n u m s [ j ] dp[i]=\max_{j=0}^{i-1} \{dp[j]+1\},\quad \text{if}\, nums[i] > nums[j] dp[i]=j=0maxi−1{dp[j]+1},ifnums[i]>nums[j]
其中, n u m s nums nums 表示原数列。
代码中,使用双重循环来计算 d p dp dp 数组。外层循环遍历所有元素,内层循环遍历当前元素前面的所有元素,如果存在一个元素小于当前元素,那么就可以将当前元素添加进该元素为结尾的最长上升子序列中,从而得到以当前元素为结尾的最长上升子序列。
循环结束后, d p dp dp 数组中的最大值即为整个数列的最长上升子序列长度。文章来源:https://www.toymoban.com/news/detail-620498.html
需要注意的是,以上代码中没有考虑数列中存在相同元素的情况。如果数列中存在相同元素,那么在转移时应该将条件 n u m s [ i ] > n u m s [ j ] nums[i] > nums[j] nums[i]>nums[j] 改为 n u m s [ i ] > n u m s [ j ] and d p [ i ] ≤ d p [ j ] nums[i] > nums[j] \, \text{and} \, dp[i] \leq dp[j] nums[i]>nums[j]anddp[i]≤dp[j],保证子序列的单调性和最长性质。文章来源地址https://www.toymoban.com/news/detail-620498.html
题解
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//动态规划 dp[i]为到i位置的最长严格递增子序列,结果输出dp[n-1]
vector<int> dp(nums.size(),1);//最小值为1
for(int i=1;i<dp.size();i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j])
dp[i] =max(dp[i],dp[j]+1);
}
}
int res = 0;
for(int i=0;i<dp.size();i++){
cout<< dp[i]<<",";
res = max(dp[i],res);
}
return res;
}
};
错解
#include <stdio.h>
#include<vector>
#include<memory>
#include<iostream>
#include<algorithm>
using namespace std;
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//动态规划 dp[i]为到i位置的最长严格递增子序列,结果输出dp[n-1]
vector<int> dp(nums.size(),1);//最小值为1
for(int i=1;i<dp.size();i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j])
dp[i] =max(dp[i],dp[j]+1);
else
dp[i] = 1;//前边没有更小的值了 应该去掉这个else部分
}
}
int res = 0;
for(int i=0;i<dp.size();i++){
cout<< dp[i]<<",";
res = max(dp[i],res);
}
return res;
}
};
int main()
{
vector<int> arr = {7,7,7,7,7,7,7};//{10,9,2,5,3,7,101,18};
unique_ptr<Solution> mysolo = unique_ptr<Solution>(new Solution());
int res = mysolo->lengthOfLIS(arr);
cout<<res<<endl;
return 0;
}
到了这里,关于leetcode300. 最长递增子序列 子序列(不连续)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!