dp专题18 最长上升子序列

本题链接:晴问算法

题目:dp专题18 最长上升子序列_第1张图片

样例:

输入
7
1 2 3 -1 -2 7 9

输出
5

思路:

        根据题目意思,求出最长上升子序列,不是递减的序列。

子序列的含义是:      在原数组中选取元素,选取的元素顺序和在原数组中的顺序是一致的

        从中,由于是上升的子序列,所以我们只能从头到尾的选取。

        这里我们明确一下 dp[ i ] 的含义,由于我们是从头到尾的选取,寻找最长的上升子序列,

所以我们确定   dp[ i ] 含义就是当前下标  i  的最长上升子序列长度是多少。其中 i 就是原数组的下标位置。

        所以得出一个 for  循环 

for(int i = 1;i < nums.size();++i)

        又因为我们是从头到尾的一个一个进行查看当前下标 i 的选取,所以又得到一个 for 循环作为选取元素作用

for(int j = 0;j < i;++j)

        确定好遍历顺序后,明确 dp 初始化,  由于我们最长上升子序列,所以,我们最少都有一个长度 1 作为上升子序列,所以 dp 初始化可以 是 都为 1.

        确定 dp 公式,我们是  最长上升子序列,所以我们选取的过程中,判断一下,当前的 i 的元素是否大于或者等于 我们选取的之前的元素的最大,然后取 max 即可。

       

if(nums[i] >= nums[j]) dp[i] = max(dp[i],dp[j] + 1);

代码详解如下:

#include 
#include 
#include 
#define endl '\n'
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;

inline int lengthOfLIS(vector& nums) 
{
	int sz = nums.size();
	vectordp(sz + 1,1);	// dp 初始化 1	
	int ans = 1;
	for(int i = 1;i < sz;++i)
	{
		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;
}

int main()
{
	IOS;
	int n;
	vectorv;
	cin >> n;
	while(n--)
	{
		int x;
		cin >> x;
		v.emplace_back(x);
	}
	
	int ans = lengthOfLIS(v);
	
	cout << ans << endl;
	
	return 0;
}

最后提交:dp专题18 最长上升子序列_第2张图片

你可能感兴趣的:(DP训练,算法笔记,算法)