递归和动态规划都是将原问题拆分成多个子问题然后求解,但是动态规划存储了子问题的解,不需要重复计算.

动态规划(Dynamic Programming,DP)需要转移方程和边界条件

目录

一、70. 爬楼梯

1.1 题目描述

1.2 代码

二、198. 打家劫舍

2.1 题目描述

2.2 代码

三、213. 打家劫舍 II

3.1 题目描述

3.2 代码

四、信件错排

4.1 题目描述

4.2 代码

五、母牛生产

5.1 题目描述

5.2 代码


1.1 题目描述

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

1.2 代码

思路链接

思路和算法:

用 f(x)表示爬到第 x级台阶的方案数,考虑最后一步可能跨了一级台阶,也可能跨了两级台阶。

1.动态规划的转移方程:

f(x) = f(x - 1) + f(x - 2)

2.再讨论边界条件:我们是从第 0 级开始爬的,所以从第 0 级爬到第 0 级我们可以看作只有一种方案,即 f(0) = 1;从第 0级到第 1 级也只有一种方案,即爬一级,f(1) = 1。根据转移方程得到 f(2) = 2,f(3) = 3,f(4) = 5,……

public int climbStairs(int n){int pre1=1,pre2=1;for (int i = 1; i < n; i++) {int temp=pre2pre2=pre1+pre2;pre1=temp;}return pre2;}

复杂度分析:

时间复杂度:循环执行 n 次,每次花费常数的时间代价,故渐进时间复杂度为 O(n)。

空间复杂度:这里只用了常数个变量作为辅助空间,故渐进空间复杂度为 O(1)。

补充

还有两种其他方法:

  • 随着 n的不断增大 O(n) 可能已经不能满足我们的需要了,我们可以用「矩阵快速幂」的方法把算法加速到O(logn)。
  • 我们也可以把 n 代入斐波那契数列的通项公式计算结果,但是如果我们用浮点数计算来实现,可能会产生精度误差。

二、198. 打家劫舍

2.1 题目描述

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

2.2 代码

题解思路

如果房屋数量大于两间,应该如何计算能够偷窃到的最高总金额呢?对于第 k (k>2) 间房屋,有两个选项:

  • 偷窃第 k 间房屋,那么就不能偷窃第k−1 间房屋,偷窃总金额为前k−2 间房屋的最高总金额与第 k 间房屋的金额之和。f(k-2)+mk
  • 不偷窃第k 间房屋,偷窃总金额为前 k−1 间房屋的最高总金额。f(k-1)

如果有一间房,则偷这一间f1=m1。若有两间房,则偷金额多的那一个f2=max{m1,m2}。如果有三间房,则f3=max{{m1,m3},{m2}},即f3=max{f1+m3,f2}。

如果有四间房,若偷前两间房的最大的加上第4间,或者前3间房的,即{f2+m4}or f3,因此f4=max{{f2+m4},f3}。

可以写出转移方程:

public static int rob(int[] nums) {if (nums.length==1) return nums[0];int pre1=nums[0],pre2=Math.max(nums[0],nums[1]);for (int i = 2; i < nums.length; i++) {int temp=pre2;pre2=Math.max(pre1+nums[i],pre2);pre1=temp;}return pre2;}

复杂度分析

时间复杂度:O(n),其中 n是数组长度。只需要对数组遍历一次。

空间复杂度:O(1)。使用滚动数组,可以只存储前两间房屋的最高总金额,而不需要存储整个数组的结果,因此空间复杂度是 O(1)。

三、213. 打家劫舍 II

3.1 题目描述

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

3.2 代码

题解思路

假设数组nums 的长度为 n。如果不偷窃最后一间房屋,则偷窃房屋的下标范围是[0,n−2];如果不偷窃第一间房屋,则偷窃房屋的下标范围是 [1,n−1]。

在确定偷窃房屋的下标范围之后,即可用第 198 题的方法解决。

public static int rob(int[] nums) {int n=nums.length;if (nums==null || n == 0) return 0;if (n == 1) return nums[0];if (n == 2) return Math.max(nums[0], nums[1]);return Math.max(robRange(nums,0,n-2),robRange(nums,1,n-1));}public static int robRange(int[] nums,int start,int end){int pre1 = nums[start], pre2 = Math.max(nums[start], nums[start+1]);for (int i = start+2; i <= end; i++) {int temp=pre2;pre2 = Math.max(pre1 + nums[i], pre2);pre1 = temp;}return pre2;}

四、信件错排

4.1 题目描述

  NowCoder每天要给很多人发邮件。有一天他发现发错了邮件,把发给A的邮件发给了B,把发给B的邮件发给了A。于是他就思考,要给n个人发邮件,在每个人仅收到1封邮件的情况下,有多少种情况是所有人都收到了错误的邮件?

即有 N 个信件和信箱,每封信件对应一个正确信箱位置。现在它们被打乱,求错误装信方式的数量。保证每一封信都装在错误的位置。

4.2 代码

思路:

数组dp[],存储错误方式数量。dp[i]表示有i封信、i个信箱情况下的错误装信方法总数。

对于第N封信而言,假设其装在了第 K 个信箱中,对于第 K 封信,有两种情况,(1)信件 K 装在信箱 N 中;(2)信件 K 未被装在信箱 N 中。

(1) 信件K装在信箱N中

我们不看 K 和 N 这两对信件和信箱,只关注剩下 N-2 对信件和信箱,有 dp[N-2] 种错误装信方法。同时, K 的取值范围: 1~N-1 ,因此共有 (N-1)*dp[N-2] 种错误装信方法。

(2) 信件 K 未被装在信箱 N 中

先给出结果,该情况的错误装信方法有 (N-1)*dp[N-1] 种。这个 dp[N-1] 是如何得出来,我思考了良久。

我们把问题重新描述一下,思路就会清晰很多。事实上,对于信件 i 来说,信箱 i 是它的“专属信箱”,每个信件都不能放入自己的专属信箱,对于n 个信件而言,都需要找其它 n-1 个信箱放入,其错排方法数为 dp[n] 。

问题的症结在于,对于上图中的信件 K 来说,其专属信箱,即 K 信箱已经被占用。

但是,我们可以把信箱 N 当做信件 K 的“专属信箱”,因为本情况下,信件 K 也不能放入信箱 N 。所以可以理解成求 N-1 封信件和 N-1 个信箱(除去信件 N)之间的错排数量问题。所以得到 dp[N-1]。

同理 K 的取值范围: 1~N-1 ,因此共有 (N-1)*dp[N-1] 种错误装信方法。

综上,状态转移方程

 private int MailMisalignment(int n){if (n==0) return 0;if (n==1) return 1;int[] dp =new int[n];dp[0]=0;dp[1]=1;for (int i = 2; i < n; i++) {dp[i]=(i-1)*(dp[i-1]+dp[i-2]);}return dp[n-1];}

五、母牛生产

5.1 题目描述

  假设农场中成熟的母牛每年都会生 1 头小母牛,并且永远不会死。第一年有 1 只小母牛,从第二年开始,母牛开始生小母牛。每只小母牛 3 年之后成熟又可以生小母牛。给定整数 N,求 N 年后牛的数量。

5.2 代码

思路:

  每一年的母牛数等于前一年的母牛数和三年前的母牛数。用dp[i]代表第i+1年的母牛数量。

转移方程:dp[ i ]=dp[i-1]+dp[i-3]

边界条件:dp[0]=1;dp[1]=2;dp[2]=3;//第一年有1个母牛,第二年有2个,第三年有3个母牛

  public  int cowNums(int n){if (n<=3) return n;int dp[]=new int[n];dp[0]=1;dp[1]=2;dp[2]=3;for (int i = 3; i <n ; i++) {dp[i]=dp[i-1]+dp[i-3];}return dp[n-1];}

动态规划——斐波那契数列(70. 爬楼梯、198. 打家劫舍、213. 打家劫舍II、信件错排、母牛生产)相关推荐

  1. 力扣算法 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯

    学习内容 力扣算法 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯 具体内容 509. 斐波那契数 斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 .该数列由 0 ...

  2. D38| DP理论基础 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯

    DP理论基础 重要知识点: 1.动规和贪心的区别:动规是由前一个状态推导出来的,而贪心是局部直接选最优的 2.动规五部曲: 1)确定dp数组(dp table)以及下标的含义 2)确定递推公式 3)d ...

  3. LeetCode:递归思想的延伸,从斐波那契数列到爬楼梯模型

    题目描述: 假设你正在爬楼梯.需要 n 阶你才能到达楼顶.每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 看到这个问题的第一反应其实我想到的是排列组合的思想去解答.比如有n阶, ...

  4. 【力扣动态规划基础专题】:509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯 62. 不同路径 63. 不同路径 II 343. 整数拆分 96. 不同的二叉搜索树

    /** 动态规划专题:这是最简单的并且已经给出了转移方程,平时我们用dp[]数组来表示转移方程转移方程: dp[n] = dp[n-1]+dp[n-2]初始值:dp[0] = 0 , dp[1] = ...

  5. 【第37天】斐波那契数列与爬楼梯 | 迭代的鼻祖,递推与记忆化

    本文已收录于专栏

  6. Python 实现 动态规划 /斐波那契数列

    1.斐波那契数列 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为&quo ...

  7. 【恋上数据结构】递归(函数调用过程、斐波那契数列、上楼梯、汉诺塔、递归转非递归、尾调用)

    递归(Recursion) 什么是递归? 函数的调用过程(栈空间) 函数的递归调用过程 递归实例分析(1 + 2 + 3 + ... + 100 的和) 递归的基本思想.使用套路 斐波那契数列 fib ...

  8. 算法—斐波拉契数列(跳楼梯问题)

    问题描述: 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 这道题一看,就会轻易的知道用递归,f(1)=1;f(2)=1;f(n)=f(n-1)+f(n-2 ...

  9. 超级台阶 动态规划+斐波那契数列+打表(水题)

    描述 有一楼梯共m级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第m级,共有多少走法? 注:规定从一级到一级有0种走法. 输入 输入数据首先包含一个整数n(1<=n<=100), ...

最新文章

  1. java输出一个Int数据的补码
  2. 激励和设定可实现的目标是任何学习成功的关键。
  3. SPOJ_SUBLEX
  4. .NetCore 2.1以后的HttpClient最佳实践
  5. Hystrix 简介和使用
  6. 04 理解SQL与T-SQL的概念测试分析 1214
  7. android sim卡命令,Android常用命令
  8. MSB与LSB的含义
  9. 史上最经典Java入门基础视频,没有之一!
  10. 兼容 IE、 FireFox 的 javascript 日历控件 原创作者:寒羽枫(cityhunter172)
  11. easyUI1.7学习第一天_menu表单
  12. sql跟oracle的区别吗,扫盲文:oracle跟sql server的十大区别
  13. 泛泰升级包下载工具Windows版介绍_下载_使用说明_编写原理[2014.3.24更新v0.3]
  14. Java实现给PDF每页右上角添加图片水印
  15. 修改linux系统的时间PRC,Ubuntu16.04操作系统环境下修改时区
  16. python图像处理:PIL与Pillow区别
  17. 【单片机毕业设计】【mcuclub-cl-015】基于单片机的地铁到站检测的设计
  18. java:JAVA获取日期时间加一年或加一月或加一天
  19. 外夹式超声波流量计工作原理及优缺点
  20. android实现电量控制,Android 删除/定制桌面电量控制插件

热门文章

  1. Java总结之基础篇
  2. 从数据分析角度谈谈谁才是这个夏天的无价之姐——基于弹幕文本分析
  3. 高效工程师系列(一) 如何找到一个利于自己成长的环境
  4. 免费wiki系统php,HDWiki
  5. Armbian搭建本地Gitea服务器
  6. 如何将ai转换为html,如何用AI输出html网页?AI画的图片-存储为web及所有格式-放到网页有锯齿?...
  7. 轨物范世:华为手机的影像哲学
  8. Swift Archiving序列化
  9. 微型计算机从外观上看可以分为,冯.诺依曼计算机 1.3 计算机系统的组成 计算机系统概述 EDVAC的3个特点:...
  10. 傲梅轻松备份linux,傲梅轻松备份官方下载_傲梅轻松备份最新版_傲梅轻松备份5.7免费版-华军软件园...