【知识讲解-题目讲解】算法系列之动态规划入门(上)


目录

前言

[Part1. 爬楼梯](#Part1. 爬楼梯)

[Part2. 打家劫舍](#Part2. 打家劫舍)

[Part3. 完全平方数](#Part3. 完全平方数)

[Part4. 零钱兑换](#Part4. 零钱兑换)

[Part5. 结语](#Part5. 结语)


前言

动态规划作为经典的算法之一,他广泛分布在面试题,竞赛题当中,是我们非常有必要了解的算法。接下来,跟随小编的步伐来窥见这个算法的精妙吧。


let's go!!!!!!!!!


Part1. 爬楼梯

正所谓:"九层之台,起于累土。千里之行,始于足下。" 要理解动态规划这个蕴含着丰富内涵的算法,我们要先从最基础的模型开始理解。接下来,让我们来看看吧:


Leetcode链接:70. 爬楼梯 - 力扣(LeetCode)
这道题的关键就在于:我们要反向去思考。也就是:



那么我们要怎么解决这个问题呢?关键在于保留数值,我们要计算n处的方法数,就要知道n-1和n-2他们两个的方法数,n处的方法数也只与这两个有关。

同时,我们已经知道的信息是前面的方法数,n=1处他的方法数就为1,n=2处方法数就为2,我们就可以推导出三,二和三就可以推导出四,循环往复。即我们有:


cpp 复制代码
int climbStairs(int n) {
    //特殊情况讨论
    if(n==1)
    return 1;
    if(n==2)
    return 2;
    //初始化变量
    int left=1;//从前往后算
    int right=2;
    int move=0;
    n-=2;
    //主循环
    while(n--)
    {
        move=left+right;//不断滚动向前 进行n次
        left=right;
        right=move;
    }
    //return
    return move;
}

这样我们就解决了这个问题,总结以上我们的推导过程我们就可以总结出:

"++对于动态规划类的题目,我们要反向思考(后面的状态是由++ ++前面决定的),++ ++正向实现(前面保留状态推导后面的,后面的结合前面的,再推导更后面的,循环往复。)++"

接下来我们还会不断深化这个结论。


Part2. 打家劫舍

先来看题目:



Leetcode链接:198. 打家劫舍 - 力扣(LeetCode)
首先,第一点(反向思考):



其次,我们要怎么算出来S4和S5呢(正向实现):



我们来看看代码实现吧:


cpp 复制代码
int max(int a,int b)
{
    return a>b?a:b;//返回最大值
}
int rob(int* nums, int numsSize) {
    if(numsSize==1)//特殊情况讨论
    {
        return nums[0];
    }
    int left=0;
    int right=0;
    int* dp=(int*)malloc(numsSize*sizeof(int));//dp数组存最值 dp[x]~Sx
    for(int i=0;i<numsSize;i++)
    {
        dp[i]=max((i-2<0)?0:dp[i-2],(i-3<0)?0:dp[i-3])+nums[i];//按照上面所讲的公式 同时要注意数组越界的情况
    }
    return max(dp[numsSize-1],dp[numsSize-2]);
}

这样我们就完成了这道题,看起来还是比较简单的对吧,只要遵守上面的总结:反向思考,正向实现。就可以解决啦,我们来看下一个:


Part3. 完全平方数

先来看题目:



Leetcode题目链接:279. 完全平方数 - 力扣(LeetCode)
首先,反向思考:



通过上面的过程,我们已经知道了求值的手段,接下来我们来看看正向实现吧。
正向实现:



基本的逻辑理顺了,我们来看代码实现:


cpp 复制代码
int numSquares(int n) {
    //初始化变量
    int* min_sum=0;
    int m=0;//循环参数 主循环 为min_sum赋值
    int q=0;//循环参数 副循环 遍历得出min_sum的值
    int min_may=INT_MAX;//可能的最小的平方数
    int tem1=0;//临时变量1
    int tem2=0;//临时变量2
    //开辟数组min_sum
    min_sum=(int*)malloc((n+1)*sizeof(int));//存储前面的最小完全平方数组成数
    min_sum[0]=0;//0固定为0 方便本身是完全平方数的计算
    //遍历数组
    for(m=1;m<=n;m++)//从前往后走 一步一步算出每一步的最小完全平方数组成数
    {
    for(q=1;;q++)//遍历每个完全平方数
    {
    tem1=m-q*q;
    if(tem1<0)
    break;
    else
    {
    tem2=min_sum[tem1]+1;
    if(tem2<=min_may)
    {
    min_may=tem2;//维护最小完全平方数组成数
    }
    }
    }
    min_sum[m]=min_may;
    min_may=INT_MAX;//记得每一次要还原哦
    }
    //return
    return min_sum[n];//返回n处的最小完全平方数组成数
}

这道题依旧贯彻我们上面的思想,我们来看最后一题:


Part4. 零钱兑换

先来看题目:



Leetcode题目链接:322. 零钱兑换 - 力扣(LeetCode)
其实我们一看就会发现,这道题和完全平方数非常相似。都是要用一些特殊的数字凑出一个数字,上面是完全平方数,这里就是给出的数字。由于完全平方数有1的存在,所以每个数都可以凑出来,而这里不是这样的。不过也还是非常相似,我们来看代码:

cpp 复制代码
int coinChange(int* coins, int coinsSize, int amount) {
	//初始化变量
	int* min_num = (int*)malloc((amount + 1) * sizeof(int));//存储每个位置由给出的数字最少组成数目
	min_num[0] = 0;
	int move = 1;
	int* result = (int*)malloc(coinsSize * sizeof(int));//存储当前数字减去每个给出数字的结果 方便后续使用
	int min = INT_MAX;
	//循环
	while (move <= amount)//由左向右遍历 直到到达目标数字
	{
		for (int i = 0; i < coinsSize; i++)
		{
			result[i] = move - coins[i];//得到当前数字减去给定数字的全部结果
		}
		for (int i = 0; i < coinsSize; i++)
		{
			if (result[i] < 0)//小于0不用管
			{
				continue;
			}
			if (min_num[result[i]] < min&&min_num[result[i]]!=-1)
			{
				min = min_num[result[i]] + 1;//当这个不为-1时 更新最小值
			}
		}
		if (min != INT_MAX)
		{
				min_num[move] = min;//记录最小值
		}
		else
		{
			min_num[move] = -1;//当这个最小值没改变时 说明这个位置不能被给出的数字组成
		}
		min = INT_MAX;//还原
		move++;//往后走
	}
	return min_num[amount];
}

同样是贯彻了我们上述的思想,结合上面完全平方数的流程,还是非常easy的。


Part5. 结语

通过上面对4道题目的介绍,我们初步了解了动态规划算法。我认为:反向思考,正向实现,是这些题目比较普适的思想。

希望这篇博客可以给大家带来帮助。
最后,祝大家可以:春风得意马蹄疾,一日看尽长安花!

最后的最后,要是觉得本文还可以的话,可以点点赞,关注小编一波,谢谢大家!~

相关推荐
菜菜的顾清寒1 小时前
力扣HOT100(46)将有序数组转换为二叉搜索树
算法·leetcode·职场和发展
随意起个昵称9 小时前
区间dp-基础题目1(石子合并)
算法·动态规划
吞下星星的少年·-·10 小时前
线段树模板
算法
段一凡-华北理工大学10 小时前
2026 高炉炼铁智能化技术全景与演进路径~系列文章11:演进路径与行业未来
大数据·网络·人工智能·算法·工业智能体·高炉炼铁智能化
叶小鸡10 小时前
小鸡玩算法-力扣HOT100-多维动态规划
算法·leetcode·动态规划
星马梦缘11 小时前
aaaaa
数据结构·c++·算法
菜菜的顾清寒11 小时前
力扣HOT100(42)链表-随机链表的复制
算法·leetcode·链表
lqqjuly11 小时前
模型剪枝与稀疏化:理论、算法与可运行实现
人工智能·算法·剪枝
逻辑君12 小时前
Foresight研究报告【20260011】
人工智能·线性代数·算法·矩阵