动态规划学习记录,深度解析。

系列文章目录

系列文章目录

文章目录

前言

一、动态规划是什么?

二、带入题目理解

1.题目

2.思路1.

代码

总结

这代码的时间度可以发现非常大假设数组长度为n那么一共有2的n次方给子序列,而每一个子序列我们都需要去遍历一次。时间复杂度为o(n*2^n)非常满。

思路二

代码

总结

思路三

代码

总结



前言

帮助之间理解动态规划的一篇文章。

一、动态规划是什么?

1.是一中减少时间复杂度的算法。

2.避免了在计算中大量的重复计算。

3.算法本质上是利用了空间换时间思想。(后面会解释)

二、带入题目理解

1.题目

给你应该无序不重复数组nums={1,6,3,5,4},要求我们找出其中最长的递增的子序列。

2.思路1.

这里的1 3 4 和1 3 5是其中的答案。那么我应该怎么做,我先想到使用递归,从最初开始递归,比它大就进行函数调用,并且最大子序列加一,退出条件就是递归到最后。每次递归后在进行一个最大值的比较,代码实现。

代码

#include<bits/stdc++.h>
using namespace std;
int nums[]={1,6,3,5,4};
int n=5;
int mm(int m)//求当前数的最大子序列长度的函数
{
	if(m==n-1)//到达最后子序列只有一
	{
		return 1;
	}
	int max_m=1;//最大子序列长度;
	for(int j=m+1;j<n;j++)
	{
		if(nums[j]>nums[m])
		{
			max_m=max(max_m,mm(j)+1);
		}
	}
	return max_m;
}
int main(){
	int mmm=0;
	for(int i=0;i<n;i++)
	{
		mmm=max(mmm,mm(i));
	}
	cout<<mmm;
} 

总结

        这分代码的时间度可以发现非常大假设数组长度为n那么一共有2的n次方给子序列,而每一个子序列我们都需要去遍历一次。时间复杂度为o(n*2^n)非常大。

思路二

那是不是又什么办法进行优化,观察模拟过程

我们可以发现在 我们在遍历1 3 4的时候就已经计算处理4的最大子序列长度,后面1 4的时候又进行了一次计算。可以发现我们进行大量的重复计算。那么应该如何处理。这里就用到了空间换时间的思想,我只需要开一共空间(mapp)记录已经计算过的答案,那么在遇到的时候直接进行调用就可以了,这也是动态规划的一般思路。

代码

#include<bits/stdc++.h>
using namespace std;
int nums[]={1,6,3,5,4};
int n=5;
int mapp[5]={0};
int mm(int m)//求当前数的最大子序列长度的函数
{
	if(m==n-1)//到达最后子序列只有一
	{
		return 1;
	}
    if(mapp[m]!=0)
    {
        return mapp[m];
    }
	int max_m=1;//最大子序列长度;
	for(int j=m+1;j<n;j++)
	{
		if(nums[j]>nums[m])
		{
			max_m=max(max_m,mm(j)+1);
		}
	}
mapp[m]=max_m;
	return max_m;
}
int main(){
	int mmm=0;
	for(int i=0;i<n;i++)
	{
		mmm=max(mmm,mm(i));
	}
	cout<<mmm;
} 

 可以发现运行时间大大降低。

总结

通过将已经算出的答案进行记录,后面遇到了直接调用。

思路三

那么在尝试了递归,我们也可以尝试非递归。

从前面的介绍知道我们要计算从一开始的最长子序列递增长度,需要依次检查后面的所有数

的最长子序列递增长度可以得到 1 的最长子序列递增长度=max(后面的数的子序列递增长度)+1,检查从6开始的最长子序列递增长度需要依次计算后面的所有数.那我们可以得到。

最后一共长度为1;

 可以发现我们只需要从后往前依次的计算,就能把所有答案推算出来

代码

#include<bits/stdc++.h>
using namespace std;
int main(){
	int l[5]={1,1,1,1,1};
	int nums[]={1,6,3,5,4};
	for(int i=4;i>=0;i--)//从下往上计算 
	{
		for(int j=i+1;j<=4;j++)//计算后面的数 
		{
			if(nums[j]>nums[i])
			{
				l[i]=max(l[i],l[j]+1);
			}
		}
		 
	}
	cout<<max(l);//输出l中最大的即可 
} 

 这里举例了简单的案例,方便自己跟着模拟。

总结

这里的复杂度降到了(n^2),这就是最终的动态规划。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

关于不上作者榜就原神启动那件事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值