【算法】动态规划:适合新手的动态规划入门常见题目详解

本文介绍了动态规划的基本概念、特点,并通过斐波那契数列、爬楼梯、最大连续子数组和、打家劫舍四个经典题目详细阐述动态规划的解题步骤,包括状态定义、初始化和状态转移方程,帮助新手掌握动态规划的思路和应用。
摘要由CSDN通过智能技术生成

一、什么是动态规划

1.官方定义

动态规划(英语:Dynamic programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。动态规划往往用于优化递归问题,例如斐波那契数列,如果运用递归的方式来求解会重复计算很多相同的子问题,利用动态规划的思想可以减少计算量。

2.动态规划的特点

看官方的解释大家应该都会比较懵,通俗的来讲,动态规划就是大事化小,小事化无。要解决一个大问题就将大问题拆解成小问题,通过逐个解决这些小问题,最终解决问题。
动态规划可以说是递归方法的一种优化,在递归问题中,我们需要进行大量的重复计算过程,时间复杂度极高。于是就有了将计算过的结果保存起来,每一个子问题只需要计算一次就好。动态规划实际也是使用 空间换时间 的一种做法。于是动态规划问题就具有这样的特点:

  • 问题可以逐步拆解
  • 所有子问题只需解决一次
  • 对子问题进行存储

在解决动态规划问题时,通常就是以下三个步骤:

  1. 状态定义
  2. 初始化
  3. 状态转移方程

如果你还不是很懂这些个名词的意思,那就通俗的讲一下:
状态定义 :在我们使用空间换取时间时,当然要定义一个可以存储每一个子问题的结果的集合,那对于这个集合的每一个元素代表的意义一定要明确。当我们选定存储集代表的意义时,就完成了状态定义。
初始化 :最大的问题逐步分解为小问题,从最小的问题开始解决时往往我们是知道结果的,就需要将最原始的子问题的值初始化出来。
状态转移方程 :通常这也是最难想出来的一部分,我们从小问题逐步解决,状态转移方程就体现了“逐步”这一过程,列出状态转移方程可以经过多次套用由最小的问题逐步解决。

要完全理解还是要通过题目加深印象,接下来由简到难逐步来几个题目帮助理解:

二、题目练练手

1.斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为
0)。
n<=39
int Fibonacci(int n)
斐波那契数列:
1 1 2 3 5 8 13 21 …

斐波那契数列应该是递归的入门题目了,但使用递归显然耗时太多,今天就换一种解法,使用动态规划来解决。
我们按照三个步骤来:

状态定义:
首先,我们定义数组dp[ ]来存储结果,那么每一处应该存放的数字的含义是什么呢?我们要求的是数列的第n项,那不如就定义数组的第 i 处数据表示的就是斐波那契数列的第 i 项。

初始化:
我们知道斐波那契数列求解的方法是前两项之和,因此在初始化时,至少初始化前两项。题目中表示第 0 项为 0 而第一项就是 1 这就初始化好了前两项。

状态转移方程:
知道第零和第一项,怎么求第二项?当然是加起来,也就是
第二项: dp[2] = dp[1] + dp[0] ;
第三项: dp[3] = dp[2] + dp[1] ;
第四项: dp[4] = dp[3] + dp[2] ;

第n项: dp[n] = dp[n - 1] + dp[n - 2] ;
这就得到了我们的状态转移方程
接下来就是顺理成章的写代码了
代码:

public class Fibonacci {
   
    public int Fibonacci(int n) {
   
        if(n == 0)
        	return 0;
        if(n == 1 || n == 2)
        	return 1;
        //因为有第0项,所以在创建时要创建n+1长度
        int[] dp = new int[n + 1];
        //初始化
        dp[0] =</
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值