[Leedcode][JAVA][第42题][动态规划][双指针][栈]

【问题描述】

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。![image.png](https://upload-images.jianshu.io/upload_images/17025746-87f6db1a993ce416.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。示例:输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

【解答思路】

1. 栈 ->括号匹配


1.当前高度小于等于栈顶高度,入栈,指针后移。

2.当前高度大于栈顶高度,出栈,计算出当前墙和栈顶的墙之间水的多少,然后计算当前的高度和新栈的高度的关系,重复第 2 步。直到当前墙的高度不大于栈顶高度或者栈空,然后把当前墙入栈,指针后移。

3.水量:(Min ( max _ left ,max _ right ) - height [ i ] ) *两个墙之间的距离
时间复杂度:O(N) 空间复杂度:O(N)

public int trap6(int[] height) {int sum = 0;Stack<Integer> stack = new Stack<>();int current = 0;while (current < height.length) {//如果栈不空并且当前指向的高度大于栈顶高度就一直循环while (!stack.empty() && height[current] > height[stack.peek()]) {int h = height[stack.peek()]; //取出要出栈的元素stack.pop(); //出栈if (stack.empty()) { // 栈空就出去break; }int distance = current - stack.peek() - 1; //两堵墙之前的距离。int min = Math.min(height[stack.peek()], height[current]);sum = sum + distance * (min - h);}stack.push(current); //当前指向的墙入栈current++; //指针后移}return sum;
}作者:windliang
链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-8/
2. 按列 暴力

时间复杂度:O(N^2) 空间复杂度:O(1)
求每一列的水,关注当前列,以及左边最高的墙,右边最高的墙就够了。
装水的多少,当然根据木桶效应,需要看左边最高的墙和右边最高的墙中较矮的一个就够了
三种情况:

  • 较矮的墙的高度大于当前列的墙的高度 左边的墙的高度-减去当前列的高度
  • 较矮的墙的高度小于当前列的墙的高度 无水
  • 较矮的墙的高度等于当前列的墙的高度 无水
public int trap(int[] height) {int sum = 0;//最两端的列不用考虑,因为一定不会有水。所以下标从 1 到 length - 2for (int i = 1; i < height.length - 1; i++) {int max_left = 0;//找出左边最高for (int j = i - 1; j >= 0; j--) {if (height[j] > max_left) {max_left = height[j];}}int max_right = 0;//找出右边最高for (int j = i + 1; j < height.length; j++) {if (height[j] > max_right) {max_right = height[j];}}//找出两端较小的int min = Math.min(max_left, max_right);//只有较小的一段大于当前列的高度才会有水,其他情况不会有水if (min > height[i]) {sum = sum + (min - height[i]);}}return sum;
}作者:windliang
链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-8/
3. 动态规划

优化 “对于每一列,我们求它左边最高的墙和右边最高的墙,都是重新遍历一遍所有高度”
max_left [i] 代表第 i 列左边最高的墙的高度,max_right[i] 代表第 i 列右边最高的墙的高度。
image.png

时间复杂度:O(N) 空间复杂度:O(N)

public int trap(int[] height) {int sum = 0;int[] max_left = new int[height.length];int[] max_right = new int[height.length];for (int i = 1; i < height.length - 1; i++) {max_left[i] = Math.max(max_left[i - 1], height[i - 1]);}for (int i = height.length - 2; i >= 0; i--) {max_right[i] = Math.max(max_right[i + 1], height[i + 1]);}for (int i = 1; i < height.length - 1; i++) {int min = Math.min(max_left[i], max_right[i]);if (min > height[i]) {sum = sum + (min - height[i]);}}return sum;
}作者:windliang
链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-8/

优化 左右数组->左数组

public int trap(int[] height) {int sum = 0;int max_left = 0;int[] max_right = new int[height.length];for (int i = height.length - 2; i >= 0; i--) {max_right[i] = Math.max(max_right[i + 1], height[i + 1]);}for (int i = 1; i < height.length - 1; i++) {max_left = Math.max(max_left, height[i - 1]);int min = Math.min(max_left, max_right[i]);if (min > height[i]) {sum = sum + (min - height[i]);}}return sum;
}作者:windliang
链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-8/
4. 动态规划 双指针优化

(因为第一个柱子和最后一个柱子肯定不能装水,因为不作为装水柱子,而是作为左边最高柱子和右边最高柱子)
时间复杂度:O(N) 空间复杂度:O(1)

使用双指针(左右两边各一个指针)

        我们使用一根一根柱子计算装水量的方法left 表示左边当前遍历的柱子(即左边我们需要计算能够装多少水的柱子)left_max 表示 left 的左边最高的柱子长度(不包括 left)right 表示右边当前遍历的柱子right_max 表示 right 的右边最高的柱子长度(不包括 right)我们有以下几个公式:            当 left_max < right_max 的话,那么我们就判断 left_max 是否比 left 高因为根据木桶效应,一个桶装水量取决于最短的那个木板,这里也一样,柱子能否装水取决于左右两边的是否都存在比它高的柱子因为 left_max < right_max 了,那么我们只需要比较 left_max 即可如果 left_max > left,那么装水量就是 left_max - left如果 left_max <= left,那么装水量为 0,即 left 装不了水当 left_max >= right_max 的话,同理如上,比较 right_max 和 right???? 为什么 right_max 和 left 隔这么远我们还可以使用 right_max 来判断?前提:left_max < right_maxright_max 虽然跟 left 离得远,但有如下两种情况:1、left 柱子和 right_max 柱子之间,没有比 right_max 柱子更高的柱子了,那么情况如下:  left 能否装水取决于 left_max 柱子是否比 left 高||           ||   |       |↑   ↑       ↑l_m  l      r_m2、left 柱子和 right_max 柱子之间存在比 right_max 柱子更高的柱子那么情况如下:因为存在了比 right_max 更高的柱子,那么我们仍然只需要判断 left_max 是否比 left 高,因为右边已经存在比 left 高的柱子||   ||       |   ||   |   |   |↑   ↑   ↑   ↑l_m  l  mid  r_m初始化指针:left = 1;right = len - 2;left_max = 0;right_max = len - 1;(因为第一个柱子和最后一个柱子肯定不能装水,因为不作为装水柱子,而是作为左边最高柱子和右边最高柱子)
public int trap(int[] height) {int sum = 0;int max_left = 0;int max_right = 0;int left = 1;int right = height.length - 2; // 加右指针进去for (int i = 1; i < height.length - 1; i++) {//从左到右更if (height[left - 1] < height[right + 1]) {max_left = Math.max(max_left, height[left - 1]);int min = max_left;if (min > height[left]) {sum = sum + (min - height[left]);}left++;//从右到左更} else {max_right = Math.max(max_right, height[right + 1]);int min = max_right;if (min > height[right]) {sum = sum + (min - height[right]);}right--;}}return sum;
}作者:windliang
链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-8/
5. 逐行分析 超时

时间复杂度:O(N^2) 空间复杂度:O(1)
image.png

public int trap(int[] height) {int sum = 0;int max = getMax(height);//找到最大的高度,以便遍历。for (int i = 1; i <= max; i++) {boolean isStart = false; //标记是否开始更新 tempint temp_sum = 0;for (int j = 0; j < height.length; j++) {if (isStart && height[j] < i) {temp_sum++;}if (height[j] >= i) {sum = sum + temp_sum;temp_sum = 0;isStart = true;}}}return sum;
}
private int getMax(int[] height) {int max = 0;for (int i = 0; i < height.length; i++) {if (height[i] > max) {max = height[i];}}return max;
}作者:windliang
链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-8/

【总结】

  1. 动态规划,空间换时间,双指针是个好工具
    -链表题目也可以使用

2.栈->类比括号匹配

  • 当是数组入栈时,入栈下标,数组的值可以通过下标获得
  1. 横纵思考 多思考几步 想清楚所有情况再动手 !!!

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

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

相关文章

java学习(142):file类的基本创建

//file类的基本创建 import java.io.File;public class test85 {public static void main(String[] args){//创建文件对象String filePath"e:\\1.txt";File filenew File( filePath );System.out.println( filenull );//无论给定的文件虚拟路径是否存在//创建file在j…

[Leedcode][JAVA][第460题][LFU]

【问题描述】 设计并实现最不经常使用&#xff08;LFU&#xff09;缓存的数据结构。它应该支持以下操作&#xff1a;get 和 put。get(key) - 如果键存在于缓存中&#xff0c;则获取键的值&#xff08;总是正数&#xff09;&#xff0c;否则返回 -1。 put(key, value) - 如果键…

性能测试十九:jmeter参数优化+排错

一&#xff1a;参数优化 1&#xff0c;控制台取样间隔的设置&#xff0c;在jmeter/bin/jmeter.properties文件中修改 summariser.interval10&#xff0c;默认为30s&#xff0c;最低可修改为6s 2&#xff0c;Jvm参数优化 bin目录下&#xff0c;vi jmeter&#xff0c;修改HEAP的…

java学习(144):file常用方法1

import java.io.File; import java.io.IOException; import java.net.URI; import java.util.List;//文件管理类 public class FileManager {public static File createFileAction(URI uri){//使用URI做出参数创建对象if(uri!null)return new File( uri );return null;}//dir文…

[Leedcode][JAVA][第72题][动态规划]

【问题描述】 [72. 编辑距离] 给你两个单词 word1 和 word2&#xff0c;请你计算出将 word1 转换成 word2 所使用的最少操作数 。你可以对一个单词进行如下三种操作&#xff1a;插入一个字符 删除一个字符 替换一个字符示例 1&#xff1a;输入&#xff1a;word1 "horse&…

java学习(145):file常用方法2

import java.io.File; import java.io.IOException; import java.net.URI; import java.util.List;//文件管理类 public class FileManager {public static File createFileAction(URI uri){//使用URI做出参数创建对象if(uri!null)return new File( uri );return null;}//dir文…

java uipath_10.3 UiPath如何调用Java

调用Java方法(Invoke Java Method)的介绍从Java Scope中的.jar加载的方法中调用指定的Java方法。并结果存储在变量中二、Invoke Java Method 在UiPath中的使用打开设计器, 在设计库中新建一个Sequence&#xff0c;为序列命名及设置Sequence存放的路径, 在Activities中搜索Java …

java学习(146):file常用方法3

import java.io.File; import java.io.IOException; import java.net.URI; import java.util.List;//文件管理类 public class FileManager {public static File createFileAction(URI uri){//使用URI做出参数创建对象if(uri!null)return new File( uri );return null;}//dir文…

[算法][二分查找][排除法]

最基本的二分查找算法 「搜索区间」是 [left, right] nums[mid] target 时可以立即返回 int binary_search(int[] nums, int target) {int left 0, right nums.length - 1; while(left < right) {int mid left (right - left) / 2;//防止大数溢出if (nums[mid] < t…

java学习(147):字节输入流

//读取二进制文件&#xff0c;字节输入流 import java.io.*;public class FileMana {public static void readBitFile(String filename){//1建立目标要读取的文件对象File filenew File( filename );//2基于目标对象建立输入流InputStream innull;if(file.exists()){//如果文件…

[Leedcode][JAVA][面试题 01.07][找规律][旋转数组]

【问题描述】 [面试题 01.07. 旋转矩阵] 示例 1:给定 matrix [[1,2,3],[4,5,6],[7,8,9] ],原地旋转输入矩阵&#xff0c;使其变为: [[7,4,1],[8,5,2],[9,6,3] ]给你一幅由 N N 矩阵表示的图像&#xff0c;其中每个像素的大小为 4 字节。请你设计一种算法&#xff0c;将图像…

java学习(148):三个参数的输入流

//3个参数读取二进制文件 import java.io.*;public class FileManage {public static void readBitFile(String filename){//1建立目标要读取的文件对象File filenew File( filename );//2基于目标对象建立输入流InputStream innull;if(file.exists()){//如果文件存在&#xff…

[剑指offer][JAVA][面试题第13题][机器人的运动][DFS][BFS]

【问题描述】 [中等] 地上有一个m行n列的方格&#xff0c;从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动&#xff0c;它每次可以向左、右、上、下移动一格&#xff08;不能移动到方格外&#xff09;&#xff0c;也不能进入行坐标和列坐标的数位之和…

ios php rsa,RSA 加密 iOS

在iOS端使用RSA加密的记录一、需求&#xff1a;SDK开发&#xff0c;使用RSA加密和后台进行数据交互&#xff0c;后台是PHP要求&#xff1a;1、post请求&#xff0c;客户端放公钥&#xff0c;私钥放后台2、发送数据&#xff1a;客户端的json数据—>RSA加密数据—>base64编…

java学习(149):字符输入流

import javax.imageio.IIOException; import java.io.*; import java.util.Date;//字符输入流 public class FileManagerChar {public static void readCharFile(File file){FileReader fileReadernull;//文本输入流if(file.exists()){try {fileReader new FileReader( file )…

java三年,Java开发三年,你不得不了解的JVM(一)

基本概念&#xff1a;JVM 是可运行 Java 代码的假想计算机 &#xff0c;包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收&#xff0c;堆 和 一个存储方法域。JVM 是运行在操作系统之上的&#xff0c;它与硬件没有直接的交互。运行过程&#xff1a;我们都知道Java源文件…

[Leedcode][JAVA][第22题括号生成][DFS][BFS][动态规划]

【问题描述】22. 括号生成 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例&#xff1a;输入&#xff1a;n 3 输出&#xff1a;["((()))","(()())","(())()","()(…

java学习(150):文本缓冲流

import javax.imageio.IIOException; import java.io.*; import java.util.Date;//字符输入流 public class FileManagerChar {public static void readCharFile(File file){FileReader fileReadernull;//文本输入流if(file.exists()){try {fileReader new FileReader( file )…

微信小程序初始化 operateWXData:fail invalid scope

初学者开发微信小程序&#xff0c;可以使用云开发来进行微信小程序的开发。 第一次使用开发工具遇到的问题 解决方案&#xff1a;1、找到云开发 2、点击开通&#xff0c;选择合适自己的开发环境&#xff1b; 3、完成后&#xff0c;返回开发工具界面点击项目第一个节点“cloudfu…

matlab win10 gpu加速,win10的Edge浏览器设置GPU硬件加速,大幅度提升浏览器性能

不知道大家对于GPU硬件加速是否有了解&#xff0c;这是现在的浏览器必备的功能&#xff0c;开启后能大幅度提升浏览器的性能&#xff0c;给我们更加顺滑的浏览体验。GPU硬件加速能够利用GPU的图形性能&#xff0c;加速渲染网页中的图像信息。如果我们开启了GPU硬件加速&#xf…