目录

背景

实现方法

Step 1. 确定递归关系

Step 2. 递归方法实现 (top-down)

Step 3. 递归方法 + 过程存储 实现 (top-down)

Step 4. 迭代方法 + 过程存储 实现 (bottom-up)

Step 5. 迭代方法 + 2个变量 Iterative + 2 variables (bottom-up)

附:在Fibonacci序列中使用的方法


背景

在From-good-to-great.-How-to-approach-most-of-DP-problems一文中,作者详细介绍了如何从递归思想转变到迭代思想的步骤。

There is some frustration when people publish their perfect fine-grained algorithms without sharing any information abut how they were derived. This is an attempt to change the situation. There is not much more explanation but it's rather an example of higher level improvements. Converting a solution to the next step shouldn't be as hard as attempting to come up with perfect algorithm at first attempt.

实现方法

通常,用以下5步可以实现:

  1. 确定递归关系
  2. 递归方法实现 (top-down)
  3. 递归方法 + 过程存储 实现 (top-down)
  4. 迭代方法 + 过程存储 实现 (bottom-up)
  5. 迭代方法 + N个变量 实现 (bottom-up)

Step 1. 确定递归关系

面对一间屋子,robber有2个选项:

  1. rob当前屋子i;
  2. 放弃rob当前屋子i.

如果选择‘1’,则意味着robber不能rob第i-1个屋子,但是可以安全的rob得到i-2以前所有屋子的最大loot;

如果选择‘2’,则意味着robber可以安全的rob得到i-1以前所以屋子的最大loot。

可见,问题转化选择何种情形收益最大化:

  • i屋子的loot + i-2以前屋子的loot
  • i-1屋子的loot + 更靠前的loot

rob(i) = max(rob(i - 2) + currentHouseValue, rob(i - 1))

Step 2. 递归方法实现 (top-down)

缺点:多次重复计算rob第i个屋子的结果

def rob_recursive(nums):def robber(nums, i):# 终止条件if i<0:return 0# 递归公式return max(robber(nums, i - 2) + nums[i], robber(nums, i - 1))return robber(nums, len(nums) - 1)

Step 3. 递归方法 + 过程存储 实现 (top-down)

时间复杂度 O(n),空间复杂度 O(n)。后续可以去除递归栈,更好的优化算法。

def rob_recursive_memo(nums):# 利用列表存储rob第i个屋子的结果memo = [-1] * (len(nums))def robber(nums, i):# 终止条件if i < 0:return 0if memo[i] >= 0:return memo[i]memo[i] = max(robber(nums, i - 2) + nums[i], robber(nums, i - 1))return memo[i]return robber(nums, len(nums) - 1)

Step 4. 迭代方法 + 过程存储 实现 (bottom-up)

def rob_Iterative_memo(nums):if nums == []:return 0memo = [0] * (len(nums) + 1)memo[1] = nums[0]for i in range(1, len(nums)):val = nums[i]memo[i+1] = max(memo[i], memo[i-1] + val)return memo[i+1]

Step 5. 迭代方法 + 2个变量 Iterative + 2 variables (bottom-up)

We can notice that in the previous step we use only memo[i] and memo[i-1], so going just 2 steps back. We can hold them in 2 variables instead. This optimization is met in Fibonacci sequence creation and some other problems

在Step 4中,使用 memo[i] 和 memo[i-1] 这2个值就可以回溯前2步的结果。因此,只需要采用2个变量即可实现优化,大大降低空间复杂度。这种优化方式与Fibonacci序列的处理方式类似。

def rob_Iterative_2vars(nums):if nums == []:return 0prev1 = 0 # rob第i个房间后,最大lootprev2 = 0 # 前一次最大loot,也就是不rob第i个房间的最大loot#    for i in range(len(nums)):
#        tmp = prev1
#        prev1 = max(prev2 + nums[i], prev1)
#        prev2 = tmpfor i in range(len(nums)):        prev1, prev2 = max(prev2 + nums[i], prev1), prev1return prev1

附:在Fibonacci序列中使用的方法

def fib_Recursion(n):n = input_check(n)if n in (0, 1):return 1else:return fib_Recursion(n-1)+fib_Recursion(n-2)def fib_DynamicPlanning(n):n = input_check(n)array = [1]*(n+1)for i in range(2,n+1):array[i] = array[i-1] + array[i-2]return array[n]def fib_StatesCompressing(n):f0 = 1f1 = 1if n in (0, 1):return 1else:while n - 1 > 0:f0, f1 = f1, f0 + f1n -= 1return f1

198. House Robber 的递归与动态规划实现方法(Python)相关推荐

  1. 看动画轻松理解“递归”与“动态规划”

    作者 | 程序员小吴 来源 | 五分钟学算法 在学习「数据结构和算法」的过程中,因为人习惯了平铺直叙的思维方式,所以「递归」与「动态规划」这种带循环概念(绕来绕去)的往往是相对比较难以理解的两个抽象知 ...

  2. 斐波那契数列的实现(简单递归和动态规划)

    斐波那契数列的实现(简单递归和动态规划) 一.简单递归的实现 1 #include "stdafx.h" 2 #include <string> 3 using nam ...

  3. c 递归下降识别程序_看动画轻松理解递归与动态规划

    在学习「数据结构和算法」的过程中,因为人习惯了平铺直叙的思维方式,所以「递归」与「动态规划」这种带循环概念(绕来绕去)的往往是相对比较难以理解的两个抽象知识点. 程序员小吴打算使用动画的形式来帮助理解 ...

  4. sql表中只有子节点的递归_动态规划与静态规划、递归、分治、回溯

    动态规划算是运筹学或者算法中的硬骨头了.不是说算法本身有多难,而是学完用完之后还是感觉到对其领会的不够深入,一种能用其术,不知其道的感觉.在很多教材或者回答中,经常看多将动态规划放在递归这一部分中.当 ...

  5. 数据结构与算法之暴力递归改动态规划

    数据结构与算法之暴力递归改动态规划 目录 二维数组最小路径和 暴力递归改动态规划解析 任意选择数组arr中的数字,看能不能累加得到aim 1. 二维数组最小路径和 (一) 题目描述 (二) 思路 递归 ...

  6. 史上最容易理解的暴力递归和动态规划~~

    史上最容易理解的暴力递归和动态规划~~ 介绍递归和动态规划 暴力递归: 1, 把问题转化为规模缩小了的同类问题的子问题 2, 有明确的不需要继续进行递归的条件(base case) 3, 有当得到了子 ...

  7. Java企业面试算法新得体会之4递归和动态规划问题17问

    递归和动态规划问题17问 题目真的难,好些题,一点头绪都没有 12月3号

  8. 70. Climbing Stairs【leetcode】递归,动态规划,java,算法

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  9. 裴波那契数列的递归和动态规划算法

    裴波那契数列的递归和动态规划算法 一.    概论 通过对裴波那契数列的例子,分析了递归和动态规划算法的本质.并且说明了两种算法的区别. 裴波那契数列:800年前,意大利的数学家斐波纳契出版了惊世之作 ...

最新文章

  1. pymsql学习笔记
  2. java使用Maven加载JDBC:mysql-connector连接MySQL/MariaDB
  3. leetcode算法题解(Java版)-11-贪心大法
  4. Java设计模式——装饰者模式
  5. Java并发编程笔记之FutureTask源码分析
  6. 20145308刘昊阳 20145302张薇《信息安全系统设计基础》实验五:网络通信 实验报告...
  7. idea搭建springcloud项目_Eureka搭建分布式SpringCloud项目
  8. 《从零开始学Swift》学习笔记(Day 30)——选择类还是结构体呢?
  9. CSS3 Gradient渐变
  10. svn删除文件文件夹(遇到的问题解决)
  11. 扫雷游戏网页版_《我的世界》简单的两款小游戏 带你回味和同学在电脑课上的时光...
  12. 在ARM板上移植CH341驱动
  13. 网易云音乐突破版权限制
  14. 如何把高版本unity资源导入Laya
  15. 单片机学习笔记(持续更新中)
  16. CAD绘图的基本步骤和重点
  17. Apache Tomcat 文件包含漏洞(CNVD-2020-10487/CVE-2020-1938)
  18. 【2018提高测试】飘雪圣域 【连通性+可持久化线段树 / 离线+权值线段树】 (详解)
  19. C语言解决打鱼晒网问题
  20. 结识51CTO学院后【51CTO学院三周年】

热门文章

  1. (四)万能的搜索 —— 1. 深度优先搜索
  2. 桌面每日一句--桌面翻译工具(有道翻译,微软翻译,Google翻译)
  3. 无损数据动态磁盘逆转为基本磁盘的方法
  4. 学计算机励志名言,程序员励志格言
  5. 致敬传统 津门传统曲艺更显“范儿”活动圆满落幕
  6. 企业付款到零钱(微信)
  7. 英语学习感悟,培养自信心,远离挫败感,人生更精彩
  8. Excel 中多行时快速生成自增长序号
  9. 修改element单选框样式
  10. Minkovski不等式