力扣刷题----42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 
输入:height = [4,2,0,3,2,5]
输出:9

自己写的

 public class Solution

 {

     public int Trap(int[] height)

     {

         int[] Theleft=new int[height.Length];

         int[] Therightside=new int[height.Length];

         int[] res=new int[height.Length];

         int result = 0;

         int left=Theleft[0];

         int right = Therightside[Therightside.Length - 1];

         for (int i = 0; i < height.Length; i++)

         {

             if (left <= height[i])

             {

                 Theleft[i] = 0;

                 left = height[i];

             }

             else

             {

                 Theleft[i] = left - height[i] ;

                 

             }

         }

         for (int i = height.Length-1; i >= 0; i--)

         {

             if (right <= height[i])

             {

                 Therightside[i] = 0;

                 right = height[i];

             }

             else

             {

                 Therightside[i] = right - height[i];

                 

             }

         }

         for (int i = 0; i < height.Length; i++)

         {

             res[i]= Math.Min(Theleft[i], Therightside[i]);

         }

         for (int i = 0; i < res.Length; i++)

         {

             result=result + res[i];

         }

         return result;

     }

 }

空间复杂度比较高 和官方的第一个题解一样

方法一:动态规划
对于下标 i,下雨后水能到达的最大高度等于下标 i 两边的最大高度的最小值,下标 i 处能接的雨水量等于下标 i 处的水能到达的最大高度减去 height[i]。

朴素的做法是对于数组 height 中的每个元素,分别向左和向右扫描并记录左边和右边的最大高度,然后计算每个下标位置能接的雨水量。假设数组 height 的长度为 n,该做法需要对每个下标位置使用 O(n) 的时间向两边扫描并得到最大高度,因此总时间复杂度是 O(n 
2
 )。

上述做法的时间复杂度较高是因为需要对每个下标位置都向两边扫描。如果已经知道每个位置两边的最大高度,则可以在 O(n) 的时间内得到能接的雨水总量。使用动态规划的方法,可以在 O(n) 的时间内预处理得到每个位置两边的最大高度。

创建两个长度为 n 的数组 leftMax 和 rightMax。对于 0≤i<n,leftMax[i] 表示下标 i 及其左边的位置中,height 的最大高度,rightMax[i] 表示下标 i 及其右边的位置中,height 的最大高度。

显然,leftMax[0]=height[0],rightMax[n−1]=height[n−1]。两个数组的其余元素的计算如下:

当 1≤i≤n−1 时,leftMax[i]=max(leftMax[i−1],height[i]);

当 0≤i≤n−2 时,rightMax[i]=max(rightMax[i+1],height[i])。

因此可以正向遍历数组 height 得到数组 leftMax 的每个元素值,反向遍历数组 height 得到数组 rightMax 的每个元素值。

在得到数组 leftMax 和 rightMax 的每个元素值之后,对于 0≤i<n,下标 i 处能接的雨水量等于 min(leftMax[i],rightMax[i])−height[i]。遍历每个下标位置即可得到能接的雨水总量。

 但是官方的双指针更优化

方法三:双指针
动态规划的做法中,需要维护两个数组 leftMax 和 rightMax,因此空间复杂度是 O(n)。是否可以将空间复杂度降到 O(1)?

注意到下标 i 处能接的雨水量由 leftMax[i] 和 rightMax[i] 中的最小值决定。由于数组 leftMax 是从左往右计算,数组 rightMax 是从右往左计算,因此可以使用双指针和两个变量代替两个数组。

维护两个指针 left 和 right,以及两个变量 leftMax 和 rightMax,初始时 left=0,right=n−1,leftMax=0,rightMax=0。指针 left 只会向右移动,指针 right 只会向左移动,在移动指针的过程中维护两个变量 leftMax 和 rightMax 的值。

当两个指针没有相遇时,进行如下操作:

使用 height[left] 和 height[right] 的值更新 leftMax 和 rightMax 的值;

如果 height[left]<height[right],则必有 leftMax<rightMax,下标 left 处能接的雨水量等于 leftMax−height[left],将下标 left 处能接的雨水量加到能接的雨水总量,然后将 left 加 1(即向右移动一位);

如果 height[left]≥height[right],则必有 leftMax≥rightMax,下标 right 处能接的雨水量等于 rightMax−height[right],将下标 right 处能接的雨水量加到能接的雨水总量,然后将 right 减 1(即向左移动一位)。

当两个指针相遇时,即可得到能接的雨水总量。

下面用一个例子 height=[0,1,0,2,1,0,1,3,2,1,2,1] 来帮助读者理解双指针的做法。

 

class Solution {public int trap(int[] height) {int ans = 0;int left = 0, right = height.length - 1;int leftMax = 0, rightMax = 0;while (left < right) {leftMax = Math.max(leftMax, height[left]);rightMax = Math.max(rightMax, height[right]);if (height[left] < height[right]) {ans += leftMax - height[left];++left;} else {ans += rightMax - height[right];--right;}}return ans;}
}

关于动态规划的介绍

动态规划(Dynamic Programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学等领域中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。

动态规划经常用于求解具有重叠子问题和最优子结构性质的问题。这里的“重叠子问题”是指在递归算法中反复出现的问题,而“最优子结构”是指问题的最优解包含其子问题的最优解。

动态规划的关键步骤:

  1. 识别子问题:将问题分解为小的子问题,这些子问题往往是原问题的规模较小的版本。

  2. 确定状态:定义问题的解状态,通常用变量表示,例如 dp[i]

  3. 确定状态转移方程:找出状态之间的关系,即当前状态是如何由之前的一个或多个状态推导出来的。

  4. 确定初始状态和边界条件:确定状态转移的起点,即基本情况或边界条件。

  5. 确定求解策略:是自底向上(从最小的子问题开始解决)还是自顶向下(递归地解决)。

  6. 构造最优解:根据子问题的解构造原问题的解。

动态规划的常见应用:

  • 斐波那契数列:计算第n个斐波那契数。
  • 背包问题:在不超过背包容量的前提下,选择物品以最大化价值。
  • 最长公共子序列:找出两个序列的最长公共子序列。
  • 最短路径问题:如贝尔曼-福特算法解决带负权边的最短路径问题。
  • 矩阵链乘问题:计算矩阵乘法的最少操作次数。
  • 编辑距离问题:计算两个字符串之间的最小编辑距离。

示例:斐波那契数列的动态规划解法

斐波那契数列是一个典型的动态规划问题,其递归解法存在大量重复计算。动态规划解法如下:

  1. 状态定义dp[i] 表示斐波那契数列的第 i 个数。
  2. 状态转移方程dp[i] = dp[i-1] + dp[i-2]
  3. 初始状态dp[0] = 0dp[1] = 1
  4. 循环计算:从 2 到 n,依次计算 dp[i]
using System;class Program
{// 动态规划计算斐波那契数列的第n项static long Fibonacci(int n){if (n <= 1)return n;long[] dp = new long[n + 1];dp[0] = 0;dp[1] = 1;for (int i = 2; i <= n; i++){dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}static void Main(){int n = 10; // 计算斐波那契数列的第10项long result = Fibonacci(n);Console.WriteLine($"Fibonacci of {n} is {result}");}
}

动态规划是一种非常强大的方法,可以显著提高算法的效率,特别是在解决具有重复子问题和最优子结构的问题时。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/51391.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP程序设计

TCP概述 建立连接 客户端和服务器端在建立连接时&#xff1a; 服务端是典型的监听接受连接的模式&#xff0c;就是ListenAccept 客户端是主动建立连接的模式&#xff0c;就是Dial Go语言中使用 net包实现网络的相关操作&#xff0c;包括我们TCP的操作。 用于建立连接的典型…

【JavaEE】阻塞队列

目录 一.阻塞队列(Blocking Queue) 1.什么是阻塞队列 2.特性 二.生产者消费者模型 1.什么是生产者消费者模型&#xff1f; 2.生产者消费模型的好处 2.1解耦合 2.2削峰填谷 三.如何在java中使用阻塞队列 四.模拟实现阻塞队列 1.加锁 2.阻塞等待实现 3.解决interru…

学习c语言第十三天(结构体)

一.结构体声明 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 描述复杂对象。 结构体成员可以是标量、数组、指针、结构体。 定义和初始化&#xff1a; struct peo {char namer[20];char tele[12];char sex[5];int high; }; s…

git 迁移仓库的方法

git Git是一个开源的分布式版本控制系统&#xff0c;由Linus Torvalds在2005年创建&#xff0c;用于有效、高速地处理从小到大的项目管理。它最初是为Linux内核开发而设计的&#xff0c;但很快被广泛用于各种项目。 以下是Git的一些主要特性&#xff1a; 分布式架构&#xff…

Python设计模式 - 工厂方法模式

定义 工厂方法模式是一种创建型设计模式&#xff0c;它定义一个创建对象的接口&#xff0c;让其子类来处理对象的创建&#xff0c;而不是直接实例化对象。 结构 抽象工厂&#xff08;Factory&#xff09;&#xff1a;声明工厂方法&#xff0c;返回一个产品对象。具体工厂类都…

4.JAVA-运算符

算数运算符 隐式类型转换 强制转换 字符串操作 字符相加 小结 自增自减运算符 赋值运算符 关系运算符 逻辑运算符 短路逻辑运算 三元运算符 运算符优先级 这里小括号优先于所有&#xff0c;所以想要哪一个优先运算&#xff0c;就可以将哪一个用小括号扩起来&#xff0c;比较方便…

酒店押金原路退回系统开通方法,手机查看报表

一、酒店押金管理有哪些&#xff1f; 1.渠道有银行预授权 2.微信押金支付 3.酒店押金系统 4.支付押金管理 二、专业酒店押金管理VS银行 序号功能专业押金系统银行预授权1收款方式支持微信、支付宝、银联app、信用卡、花呗需要带银行卡刷卡2资金安全区分房费和押金&#x…

PermissionError: [Errno 13] Permission denied

PermissionError: [Errno 13] Permission denied 目录 PermissionError: [Errno 13] Permission denied 【常见模块错误】 【错误原因】 【解决方案】 检查文件或目录的权限 确保文件路径正确 关闭其他占用文件的程序 运行程序时提升权限 更改 Python 的工作目录 示例代…

什么是职场?如何在职场中提升自己的情商?

职场这一概念&#xff0c;实质上是指在工作场所中&#xff0c;员工与员工之间、员工与组织之间相互发生作用和影响的一个特定环境。它不仅仅局限于办公室&#xff0c;还延展到会议室、休息室、餐厅等场所&#xff0c;这些场所交织成了一个错综复杂的职场生态系统。在这个系统中…

哪里可以查找短视频素材?6个素材查找下载渠道分享!

在短视频的风靡浪潮中&#xff0c;不少创作者纷纷投身于这一领域&#xff0c;无论是分享生活点滴还是进行商业宣传&#xff0c;高质量的短视频内容总能吸引众多观众的目光。然而&#xff0c;精良的短视频制作离不开优质的素材支持。本文将为大家介绍6个优秀的高质量短视频素材下…

POJ2739.Sum of Consecutive Prime Numbers

欧拉筛处理2-1e4的质数&#xff0c;再用尺取法即可 // Problem: Sum of Consecutive Prime Numbers // Contest: POJ - Japan 2005 // URL: http://poj.org/problem?id2739 // Memory Limit: 65 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.or…

[240727] Qt Creator 14 发布 | AMD 推迟 Ryzen 9000芯片发布

目录 Qt Creator 14 发布Qt Creator 14 版本发布&#xff0c;带来一系列新功能和改进终端用户可通过命令行方式查看此新闻终端用户可通过命令行方式安装软件&#xff1a; AMD 推迟 Ryzen 9000芯片发布 Qt Creator 14 发布 Qt Creator 14 版本发布&#xff0c;带来一系列新功能…

高速板开源项目学习(二)

一定要找一个高速板写的详细的等长规范&#xff1a; 看的出来&#xff0c;这位小哥也是卡着嘉立创最小免费钻孔大小来打孔的&#xff1a; 这里的天线&#xff0c;他做了禁止铺铜和走线处理&#xff0c;模拟信号在这里容易遇到干扰&#xff0c;这样是正确的&#xff0c;值得去学…

《知识点扫盲 · 线程池基础篇》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

【node】Linux下安装node和npm

Linux下安装node和npm 下面的版本虽然安装失败了&#xff0c;第一次尝试不容易&#xff0c;只需要更换一下node的版本为v16.20.2即可安装成功&#xff0c;20这样的高版本对大部分linux服务器来讲还是版本太高了&#xff0c;GLIBC动态库不支持&#xff0c;升级颇为麻烦&#xff…

她是军统美女特工,色诱汉奸一把好手!一件事之后竟......

一.前言 我们在上一篇里简单了解了什么是树&#xff0c;以及树的一种特殊结构——二叉树。而我们对二叉树息息相关的堆进行了简单的介绍。我们知道了堆是借助二叉树中完全二叉树来实现的。它实现了二叉树的顺序存储。但对于普通的二叉树来说&#xff0c;顺序存储会造成空间浪费…

贪心+背包

这道题比较坑的就是我们的对于相同截止时间的需要排个序&#xff0c;因为我们这个工作是有时间前后顺序的&#xff0c;我们如果不排序的话我们一些截止时间晚的工作就无法得到最优报酬 #include<bits/stdc.h> using namespace std;#define int long long int t; int n; c…

看板项目之vue代码分析

目录&#xff1a; Q1、vue项目怎么实现的输入localhost&#xff1a;8080就能自动跳到index页面Q2、组合饼状图如何实现Q3、vue项目如何实现环境的切换Q4、vue怎么实现vue里面去调用js文件里面的函数 Q1、vue项目怎么实现的输入localhost&#xff1a;8080就能自动跳到index页面 …

数据结构——串

语言&#xff1a;C语言软件&#xff1a;Visual Studio 2022笔记书籍&#xff1a;数据结构——用C语言描述如有错误&#xff0c;感谢指正。若有侵权请联系博主 一、串的基本概念 子串&#xff1a;串中任意连续的字符组成的子序列称为该串的子串。 主串&#xff1a;包含子串的串称…

做一个能和你互动玩耍的智能机器人之三

内容节选自英特尔的开源项目openbot的body目录下diy下的readme&#xff0c;这是一个组装和连线方式的说明文档&#xff0c;接线需要配合firmware固件使用&#xff0c;固件代码的接线柱是对应的。 body目录内部十分丰富&#xff0c;主要介绍了这个项目的背景和硬件以及如何让他…