作者:非妃是公主
专栏:《算法》《刷题笔记》
个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩

《算法》专栏系列文章

算法设计与分析复习01:主方法求递归算法时间复杂度

算法设计与分析复习02:分而治之算法

算法设计与分析复习03:动态规划算法
算法设计与分析复习04:贪心算法

算法设计与分析复习05:回溯及分支限界

算法设计与分析复习06:随机化算法

算法设计与分析复习07:样题

文章目录

  • 《算法》专栏系列文章
  • 题目:攒青豆
  • 分析
  • 源码
  • 存在问题
  • 正确思路
    • 算法思路
    • 数据结构
  • 正确源码

题目:攒青豆

现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。

分析

这道题是一道动态规划的题目,和leetcode经典题目接雨水本质是一样的。

结题的思路也是采用动态规划的思想,分为以下几种情况:

  • 从前往后遍历数组;
  • 如果当前高度高于上一个柱子高度,证明当前柱子的加入,可以继续加入豆子,导致最优解发生了变化,所以要更新前面柱子的高度。
    • 这时候,再一次进行遍历;
    • 寻找前面比当前柱子高的的柱子(可以把青豆挡住),找到后,更新寻找过程中遇到的柱子的高度较矮的柱子。
    • 如果一直找到了初始位置,也没有找到,则说明当前柱子是前面所有柱子中最高的的。这时候说明当前填充高度,为最高的柱子,取开始和当前位置的较低点。
  • 如果当前高度低于两边的高度,那么当前填充高度为左、右两个柱子中较短的高度。

源码

# include<iostream>
# include<vector>
using namespace std;int main() {vector<int> hight, curHight;hight = { 5, 2, 7, 4, 9 };curHight = hight;for (int i = 1; i < hight.size(); i++) {if (hight[i] < hight[i - 1] && i + 1 < hight.size() && hight[i] < hight[i + 1]) {curHight[i] = min(hight[i - 1], hight[i + 1]);}else if (hight[i] > hight[i - 1]) {int j;for (j = i - 1; j >= 0; j--) {if (hight[i] <= hight[j]) {break;}}if (j == -1)j = 0;int newHight = min(hight[i], hight[j]);for (int k = j + 1; k < i; k++) {curHight[k] = newHight;}}     }int sum = 0;for (int i = 0; i < hight.size(); i++) {sum += curHight[i] - hight[i];}cout << sum;
}

存在问题

但是,注意上面标红的位置,这里是存在问题的!具体是什么问题呢?这种情况下求到的最低点不一定对于前面所有位置都是最低的。具体来看如下例子:

输入:[ 5, 2, 7, 4, 9]
分析:遍历到9的时候,由于9是最大的,因此会一直遍历到初始位置5,这时候程序认为从头到后最高的高度都是5,但是,比如倒数第二个位置,这里的填充高度应该是7,不是5,因此,就出现了错误。
输出:由于程序认为最后填充后的高度都是5,所以所以做差后求解结果为2

运行程序进行输出验证,结果如下:

正确思路

算法思路

正确思路十分简洁明了:

  1. 对于每一个位置,记录他左边最高的墙,记录他右边最高的墙。
  2. 二者取较小的就是能装的最高高度。
  3. 这两个数组的初始化通过两次遍历实现。(动态规划记录的过程,记录当前最大的)
  4. 最后求解的时候,遍历一遍实际的柱子,填充到左右两边较低柱子的高度。

数据结构

用两个数组来记录两边的墙,一个记录左边的墙,另一个记录右边的墙。

用1个数组来记录真实的柱子高度。

正确源码

int main() { vector<int> hight;    // 每个位置墙的高度// 测试用例1hight = { 5,0,2,1,4,0,1,0,3 };// 测试用例2// hight = { 5, 2, 7, 4, 9 };// 当前位置两边最高的墙的高度vector<int> leftWall = vector<int>(hight.size(), 0); // 左边最高墙vector<int> rightWall = vector<int>(hight.size(), 0);// 右边最高墙// 初始化左边墙的高度int curMaxHight = hight[0];for (int i = 0; i < hight.size(); i++) {curMaxHight = max(curMaxHight, hight[i]);leftWall[i] = curMaxHight;}// 初始化右边墙的高度curMaxHight = hight[hight.size() - 1];for (int i = hight.size() - 1; i >= 0; i--) {curMaxHight = max(curMaxHight, hight[i]);rightWall[i] = curMaxHight;}// 得到当前位置可以填充的高度int sum = 0;for (int i = 0; i < hight.size(); i++) {int canFillHight = min(leftWall[i], rightWall[i]);sum += canFillHight - hight[i];}cout<<sum;
}

在测试用例1下,输出如下:

测试用例2下,输出如下:

经典动态规划OJ题目:接雨水or接青豆(多种方法,附详详细思维过程、解析及源码)相关推荐

  1. 经典怀旧FCgame红白机小游戏在线网页合集版畅玩HTML网站源码

    经典怀旧FCgame红白机小游戏在线网页合集版畅玩HTML网站源码 ☑️ 编号:ym468 ☑️ 品牌:无 ☑️ 语言:ThinkPHP ☑️ 大小:4.7MB ☑️ 类型:经典怀旧FCgame ☑️ ...

  2. 【源码那些事】超详细的ArrayList底层源码+经典面试题

  3. python动态规划详解_经典动态规划例题整理(Python版)

    由于本人的算法基础较为薄弱,所以在这里整理一下自己的做过的题,使自己能够随时随地回顾温习. 然后,本篇文章将会持续更新自己遇到的一些比较经典动态规划的题目,大家如果对代码有任何问题,直接在文章下面评论 ...

  4. python典型例题_经典动态规划例题整理(Python版)

    由于本人的算法基础较为薄弱,所以在这里整理一下自己的做过的题,使自己能够随时随地回顾温习. 然后,本篇文章将会持续更新自己遇到的一些比较经典动态规划的题目,大家如果对代码有任何问题,直接在文章下面评论 ...

  5. integral函数Opencv源码理解-leetcode动态规划的使用场景

    前言 Opencv有一个integral()函数,也就是积分图算法.有三种积分图类型,求和(sum),求平方和(sqsum),求旋转45°和(titled).根据名字可知道,前两个是统计输出每个坐标的 ...

  6. 【原创】【专栏】《Linux设备驱动程序》--- LDD3源码目录结构和源码分析经典链接

    http://blog.csdn.net/geng823/article/details/37567557 [原创][专栏]<Linux设备驱动程序>--- LDD3源码目录结构和源码分析 ...

  7. 蓝牙配对模式 java_【Android】蓝牙开发—— 经典蓝牙配对介绍(Java代码实现演示)附Demo源码...

    目录 前言 一.连接&配对方法介绍 二.演示:第一次连接蓝牙设备  &  直接与蓝牙设备建立配对 三.总结 四.补充 五.Demo案例源码地址: 前言 前面两篇文章[Android]蓝 ...

  8. cocos2dx经典魔塔游戏改编完整源码

    经典魔塔游戏改编,亲测可通过编译,完美运行,RGP+解密游戏源码 客户端:cocos2dx 服务端:单机游戏无服务端 源码连接cocos2dx经典魔塔游戏改编完整源码-cocos2D文档类资源-CSD ...

  9. 经典动态规划:0-1 背包问题

    经典动态规划:0-1 背包问题 文章目录 经典动态规划:0-1 背包问题 一.题目描述 二.动规标准套路 三.题目描述 四.解法分析 五.优化 一.题目描述 就讨论最常说的 0-1 背包问题,简单描述 ...

最新文章

  1. 在weex 中的引入 Ethereum -web3.js
  2. 算法时间复杂度和空间复杂度表示
  3. 基于keepalived对redis做高可用配置---转载
  4. 【整数反转】算法优化笔记
  5. 不要62(HDU-2089)
  6. 链表的分解(C++)
  7. respond java 使用_java – 使用android问题的HttpResponse:执行总...
  8. k3 审核流程图_3金蝶K3操作流程图详解
  9. 【Django】实现文件下载
  10. 基于JavaEE的实验室管理系统技术点
  11. 20220315_K近邻
  12. 2021年中国人工智能行业全景图谱
  13. 国培_阶段性学习总结
  14. 世界星载SAR发展8—— Discover II (发现者2)(1998,美国)
  15. 【Pyecharts50例】图表背景颜色设置
  16. 网站改版更换服务器seo,网站改版或者更换域名对网站的影响有哪些?
  17. 歌曲 Feuille d’automne 歌词及释义
  18. STM32之CubeL4 (GPIO+EXIT)
  19. 有哪些比较好的游戏图标推荐
  20. k8s client-go 程序实现kubernetes Controller Operator 使用CRD 学习总结

热门文章

  1. idea插件translation插件 提示:翻译失败: 未知错误
  2. 业务逻辑:完成客户下单后前台系统的数据处理并调用后台系统服务处理业务 webservice接口调用 有用...
  3. 中国珠算术语与计算机术语,新计算技术珠算与珠心算 王家申等编著.pdf
  4. 翻译:(MPN-Cov)Is Second-order Information Helpful for Large-scale Visual Recognition?
  5. 系统架构设计师 报考指南,考试时间
  6. 洛谷 P3964 [TJOI2013]松鼠聚会(切比雪夫距离和曼哈顿距离转换)
  7. 聊一聊前端中常说的接口
  8. ROT13加密与解密(一种加密和解密都会得到同样答案的密文)“替换式密码算法”
  9. 通过信任文件绕过火绒
  10. python能做的100件事04 - 解析PDF