来源:知乎

作者:单金折

前阵子写了两篇动态规划的文章

告别动态规划,连刷40道动规算法题,我总结了动规的套路
动态规划该如何优化?我总结了这些套路,以后优化就是分分钟

后面说要给大家讲解一些案例,不过一直没讲,由于前阵子手受伤了导致手不能运动,一直没给大家写文章,所以呢,我就找一些感觉还不错的文章供大家消费。

例1: 打家劫舍

动态规划思考步骤:

1、原问题:

在一条直线上,有n个房屋,每个房屋中有数量不等的财宝,有一个盗 贼希望从房屋中盗取财宝,由于房屋中有报警器,如果同时从相邻的两个房屋中盗取财宝就会触发报警器。问在不触发报警器的前提下,最多可获取多少财宝?例如 [5,2,6,3,1,7],则选择5,6,7

来源于LeetCode 198. House Robber

2 、子问题:

(1)、只考虑前两个房间时,谁大选谁
(2)、考虑第三个房间

  • 如果偷第三个房间,则意味着第二个房间不投,也就是第三个房间值 + 第一个房间的宝藏数量

  • 如果不偷第三个房间,则宝藏数量等于前两个房间宝藏数量

3、确认状态:

int [] nums; // 各个房间的宝藏数

int [] flags = new int [n]; // 记录各个房间有没有被偷,若flag = 0 则没偷, flag = 1 则偷了。

int [] dp = new int [n]; // dp[i]表示前i个房间偷到的最大宝藏数

4、初始状态:

第一个房间:

  • Condistion 1 :dp[0] = nums[0] ; flags[0] = 1;

  • Condistion 2 :dp[0] = 0; flags[0] = 0;

第二个房间:

  • Condistion 1 :when flags[1] = 1; dp[1] = nums[1];

  • Condistion 2 :whenflags[1] = 0; dp[1] = dp[0];

  • 选 Condistion 1 还是 Condistion 2呢?比较 两种情况下dp[1]的大小
    推广到前i个房间: (i>=2)

  • when flags[i] = 1, dp[i] = nums[i] + dp[i-2]

  • when flags[i] = 0; dp[i] = dp[i-1]

5、状态转移方程:

dp[0] = nums[0];dp[1] = max(nums[0],nums[1]);for(int i = 2;i<n;i++)    dp[i] = max(nums[i] + dp[i-2],dp[i-1])

6、代码实现

class Solution {    public int rob(int[] nums) {        if(nums.length == 0)            return 0;        int [] dp = new int[nums.length];        dp[0] = nums[0];        // 每次做数组判定时都需要做数组边界判定,防止越界        if(nums.length < 2)            return nums[0];        dp[1] = (nums[0]>nums[1]) ? nums[0] : nums[1];        for(int i = 2;i<nums.length;i++)            dp[i] = ((nums[i] + dp[i-2]) > dp[i-1]) ? (nums[i]+dp[i-2]) : dp[i-1];        return dp[nums.length-1];    }}

例2:最大子段和

动态规划思考步骤:

1、原问题

给定一个数组,求这个数组的连续子数组中,最大的那一段的和。
如数组[-2,1,-3,4,-1,2,1,-5,4] 的子段为:[-2,1]、[1,-3,4,-1]、[4,-1,2,1]、…、[-2,1,-3,4,-1,2,1,-5,4],和最大的是[4,1,2,1],为6。

示例:Input: int [] nums = [-2,1,-3,4,-1,2,1,-5,4],Output: 6Explanation: [4,-1,2,1] has the largest sum = 6.

来源于LeetCode 53. Maximum Subarray

2、子问题

  • 只考虑第一个元素,则最大子段和为其本身 DP[0] = nums[0]

  • 考虑前两个元素,最大子段和为 nums[0],num[1]以及 nums[0] + num[1] 中最大值 设为DP[1]

  • 考虑前三个元素,如何求其最大子段和?还是分为两种情况讨论,第三个元素在最后的字串内吗?

    • 若第三个元素也包含在最后的字串内,则DP[2] = Max(DP[1]+nums[2] , nums[2])

3、确认状态

DP[i] 为 以nums[i]结尾的子段的最大最短和

例如 DP[1]则为以nums[1]结尾的最大字段和

4、初始状态

dp[0] = nums[0]

dp[1] = max(dp[0]+nums[1] , nums[1])

5、状态转移方程:

dp[i] = max(dp[i-1]+nums[i],nums[i])

6、解题代码:

public class lc53_MaximumSubarray {    public int maxSubArray(int[] nums) {        int len = nums.length;        if(len == 0)            return 0;        int [] dp = new int[len];        dp[0] = nums[0];        int max = dp[0];        for (int i = 1; i<len;i++){            dp[i] = (dp[i-1]+nums[i] > nums[i]) ? dp[i-1]+nums[i] : nums[i];            if (dp[i]>max)                max = dp[i];        }        return max;    }}

例3:找零钱

已知不同面值的钞票,求如 何用最少数量的钞票组成某个金额,求可 以使用的最少钞票数量。如果任意数量的已知面值钞票都无法组成该金额, 则返回-1。

示例:Input: coins = [1, 2, 5], amount = 11Output: 3 Explanation: 11 = 5 + 5 + 1Input: coins = [2], amount = 3Output: -1

来源于LeetCode 322. Coin Change

动态规划解题步骤:

将原问题拆分成子问题

  • 已知什么?显而易见,钞票的金额都只需要其本身1张即可

  • 如何在已知钞票的情况下构造出 金额X需要的最少钞票组合

确认状态

DP[0] - DP[amount] 表示构造金额amount需要的最小钞票数

确认边界状态(初始条件)

  • DP[coin] = 1 其他的都未知初始值设为 -1

  • 例如coins = [1, 2, 5], amount = 11 已知 dp[1]、dp[2]、dp[5] =1

  • 现在已知 DP[coin] 需要求出每一个DP[amount]

状态转移方程

dp[i] = min(dp[i-1], dp[i-2], dp[i-5]) + 1

解题代码:(java)

    public int coinChange(int[] coins, int amount) {        int len = coins.length;        if (len == 0 || amount<0)            return -1;        if (amount==0)            return 0;        int [] dp = new int[amount+1];        for (int i = 0; i <= amount; i++){            dp[i] = -1;        }        for (int i = 0; i< len;i++){            if(coins[i] == amount)                return 1;            if(coins[i] < amount)                dp[coins[i]] = 1;        }        // State Transfer Function        for(int i = 1; i <= amount;i++){            for (int j = 0; j < len; j++){                if (i - coins[j] >= 0 && dp[i - coins[j]] != -1){                    if (dp[i] == -1 || dp[i] > dp[i - coins[j]] + 1){                        dp[i] = dp[i - coins[j]] + 1;                    }                }            }        }        return dp[amount];    }

总结

今天实例了三道一维的题,属于 leetcode 中 medium 级别的题吧,大家也可以根据题号去搜索练练手。

详解三道一维的动态规划算法题相关推荐

  1. 详解高斯混合模型与EM算法

    详解高斯混合模型与EM算法 详解高斯混合模型与EM算法 高斯混合模型 单高斯模型(Gaussian single model, GSM) 一维高斯分布 多维高斯分布 混合高斯模型(Gaussian m ...

  2. 【百度联盟峰会】李彦宏详解AI时代思维方式,算法驱动的降维攻击

     [百度联盟峰会]李彦宏详解AI时代思维方式,算法驱动的降维攻击 新智元 2017-05-23 14:51:52 李彦宏 手机 百度 阅读(20879) 评论(19) 新智元报道 来源:百度 [新 ...

  3. CORDIC算法详解(一)- CORDIC 算法之圆周系统之旋转模式( Rotation Mode )

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/Pieces_thinking/arti ...

  4. 中科大-计算机类考研真题(初试笔试真题详解+复试笔试机试真题详解+面试问题汇总分析)

    中科大-计算机类考研真题(初试笔试真题详解+复试笔试机试真题详解+面试问题汇总分析) 初试笔试真题2003年~2019年:答案+详解 复试面试问题总结:问题汇总+详解分析 复试面试经验总结:个人小结 ...

  5. CORDIC算法详解(五)-统一的 CORDIC 算法形式

    CORDIC算法详解(五)- 统一的 CORDIC 算法形式 文章目录 CORDIC算法详解(五)- 统一的 CORDIC 算法形式 5 统一的 CORDIC 算法形式 相关参考资料及源码   网上有 ...

  6. 一文详解基于测距的空间定位算法

    一文详解基于测距的空间定位算法 文章目录 一文详解基于测距的空间定位算法 0 定位算法分类 0.1 基于测距与非基于测距的定位算法 0.2 集中式与分布式定位算法 0.3 绝对与相对定位算法 0.4 ...

  7. 一道看完答案你会觉得很沙雕的「动态规划算法题」

    这道算法题其实并不难,如果你把文章从头到尾看完的话基本上能看懂,但如果你看到最后的话大概率会说一句:这是什么沙雕题目?! 题目来源于 LeetCode 第 877 号问题:石子游戏. 为了更好理解,我 ...

  8. 机器学习算法(二十五):KD树详解及KD树最近邻算法

    目录 1 KD树 1.1 什么是KD树 1.2 KD树的构建 1.3 KD树的插入 1.4 KD树的删除 1.5 KD树的最近邻搜索算法 1.5.1 举例:查询点(2.1,3.1) 1.5.2 举例: ...

  9. 机器学习经典算法详解及Python实现--元算法、AdaBoost

    http://blog.csdn.net/suipingsp/article/details/41822313 第一节,元算法略述 遇到罕见病例时,医院会组织专家团进行临床会诊共同分析病例以判定结果. ...

  10. 万字长文详解文本抽取:从算法理论到实践

    导读:"达观杯"文本智能信息抽取挑战赛已吸引来自中.美.英.法.德等26个国家和地区的2400余名选手参赛,目前仍在火热进行中(点击阅读原文进入比赛页面,QQ群见上图或文末二维码) ...

最新文章

  1. cimage和gdi绘图效率比较_GDI+和GDI绘图性能对比实验
  2. 16.算法调用优先于手写的循环
  3. Android开发之原型图浏览器打开可点击跳转之Google插件之Axure(实际上大部分浏览器都可以安装这个插件)
  4. Hbase 删表过程
  5. es6 Promise,生成器函数,async
  6. 【专题二】应用号(小程序)开发教程首发第二弹!(0923)
  7. Mongoose介绍和入门​​
  8. kafka使用_Kafka精华问答 | kafka的使用场景是什么?
  9. ORB_SLAM3编译
  10. Install Cockpit on Fedora/CentOS/RHEL
  11. Clear Type技术
  12. 化龙小型汽车考场手动挡C1科三考试技巧
  13. 树莓派c语言读取dht11,树莓派直接读取 DHT11 温湿度的方法
  14. QDateTime 和tm 的时间显示
  15. 0 、 '0' 、 0 、 ’\0’ 区别
  16. 2020首届海洋目标智能感知国际挑战赛 冠军方案分享
  17. Spring Boot做国际化
  18. 关闭网站服务器端口,cmd关闭端口的命令是什么_网站服务器运行维护
  19. 到底什么叫作数据集成?
  20. jadx动态调试安卓apk

热门文章

  1. JS - 解决鼠标单击、双击事件冲突问题(同时实现两种事件响应)
  2. 单机魔域mysql_魔域单机版3.2
  3. P1308 [NOIP2011 普及组] 统计单词数
  4. UI-平面构成-ai-快捷键-1
  5. 自动感应手部消毒机详细制作方案
  6. Timesnet: Temporal 2d-variation modeling for general time series analysis
  7. 谢耳朵获艾美奖最佳男主角 三夺视帝感谢男友
  8. 2020最新版前端学习路线图--Javascript网页编程重点知识
  9. 人生有三重境界:看山是山,看水是水;看山不是山,看水不是水;看山还是山,看水还是水(转载)
  10. html5酷炫动画效果网站,html5 WebGL酷炫网页动画特效