三道题带你了解动态规划

动态规划含义:,是一种将原问题分解成简单的子问题来解决复杂问题的思想。其中,动态规划还具有最优子结构性质和子问题重叠性质。

  1. 最优子结构:动态规划将原问题分解成各种简单的子问题时,各个子问题的最优解综合起来就是原问题的最优解,即局部最优解能够决定全局最优解。
  2. 子问题重叠:在计算一个子问题的最优解之后,记住这个子问题,接下来还可能遇到相同问题,为提高效率,可以直接拿来之前得到的结果,这是因为当使用递归自顶向下的时候,每次产生的子问题不总是新问题,而是之前被重复计算的问题

  斐波那契数列:0,1,1,2,3,5,8,13,21,34,55,89、、、、、、规律是从第三项开始,每一项都等于前两项之和,F(n)=F(n-1)+F(n-2),(n>=3)

求解斐波那契数列就是一个很好的递推过程,最推导后续的过程中都用到前面的推导。求导后面的必须要把前面的推导出来,一步一步向后推导,就像求解8 必须要求解出 3 ,5.

下面来看第一题

 首先来看  

  递推公式: f(i)=max{f(i−1)+nums[i],nums[i]}

  动态数组含义:当前位置的最大子数组和为多少

 我们来看一下核心代码:

举例:nums = [-2,1,-3,4,-1,2,1,-5,4]

for (int i = 0; i < nums.size(); i++)
    {
        //看一看加上之后有没有原先大  
        //这个sum 相当于找到一个比原先大的了就开始重新计算了
                   sum = max(nums[i], sum + nums[i]);
        //如果此时超过了,那么就更新
        max1 = max(sum, max1);
    }

这个sum很巧妙,在计算的过程中会随着找到最大值他就会更新,比如第一次就算,sum就是-2,但是第二次找到1比它大的就会进行更新了。之后接着往后走,当走到后面的 -1 sum又重新更新了。

来看一下全部代码:

int maxSubArray(vector<int>& nums) {
	int sum = 0;//记录当前求和的数
	int max1 = nums[0];//记录求和过程中的最大值
	for (int i = 0; i < nums.size(); i++)
	{
        //看一看加上之后有没有原先大  
        //这个sum 相当于找到一个比原先大的了就开始重新计算了
		sum = max(nums[i], sum + nums[i]);
        //如果此时超过了,那么就更新
		max1 = max(sum, max1);
	}
	return max1;
}

题二:

递推公式f(i)=max{f(i2)+nums[i],f(i-1)}

动态数组含义:就是当前服务的最长时间

核心代码:

dp[0]=nums[0] ;
dp[1]=max(nums[0],nums[1]);
    for (int  i = 2; i < dp.size(); i++)
    {
        //要么就当前不能服务了,要么就是当前的前一个没服务,当前可以服务
        dp[i] = max(dp[i - 1], dp[i - 2]+nums[i]);
    }



这道题就类似于斐波那契数列,一步一步向后推,每一个位置等于它前面的前面的位置加上当前位置的数字,或者当前不能服务,那么此时最长的服务时间就是和上一个最长的服务时间一样了。

题型三:

递推公式:f(i) =min(dpleft[i], dpright[i])-heigit[i];

动态数组含义:定义两个记录当前位置左右两边高度最高的柱子。

                          定义一个记录当前位置可以存放多少水的数组

 代码

int trap(vector<int>& height) {
	vector<int> dpleft(height.size());
	vector<int> dp(height.size());
	vector<int> dpright(height.size());
	int max1 = height[0];
	for (int i = 1; i < height.size(); i++)
	{
		if (height[i] > max1)max1 = height[i];
        dpleft[i] = max1;
	}
	max1 = height[height.size() - 1];
	for (int i = height.size()-2; i >=0; i--)
	{
		if (height[i] > max1)max1 = height[i];
        dpright[i] = max1;
	}
	int sum = 0;
	for (int i = 1; i < dp.size()-1; i++)
	{
		int min1 = min(dpleft[i], dpright[i]);
		dp[i] = min1 - height[i] > 0 ? min1 - height[i] : 0;
		sum += dp[i];
	}
	return sum;
}

dprigh记录当前位置右边最高的柱子,

dpleft记录当前位置左边最高的柱子,

当前的柱子能存放多少水,取决于当前位置左右两边最矮的柱子(水桶原理),减去当前柱子的高度,如果小于零,就让他等于0。这既是动态规划,主要是利用递推,明确好动态数组的含义。

谢谢大家观看。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值