【代码随想录】【算法训练营】【第55天】 [42]接雨水 [84]柱状图中最大的矩形

前言

思路及算法思维,指路 代码随想录。
题目来自 LeetCode。

day 55,又是一个周一,不能再坚持~

题目详情

[42] 接雨水

题目描述

42 接雨水
42 接雨水

解题思路

前提:雨水形成的情况是凹的, 需要前中后3个元素,计算该元素左右两侧的第一个大于该高度的高度
思路:单调递增栈
重点:单调栈的思维

代码实现

C语言
单调递增栈

单调递增栈: 【横向计算形成凹行柱体的雨水】
雨水形成的情况是凹的, 需要当前新的栈顶元素, 计算的是旧的栈顶元素形成的雨水

// 单调递增栈: 雨水形成的情况是凹的, 需要当前新的栈顶元素, 计算的是旧的栈顶元素形成的雨水

int minFun(int p1, int p2)
{
    return p1 < p2 ? p1 : p2;
}

int trap(int* height, int heightSize) {
    int stack[heightSize];
    int top = 0;

    // 遍历计算每个柱子接到的雨水之和
    int sum = 0;
    for (int i = 0; i < heightSize; i++) {
        // 单调递增栈
        // 当前元素比栈顶元素大,不满足单调递增栈的要求
        while (top > 0 && height[i] > height[stack[top - 1]]) {
            //  弹出当前栈顶元素
            int midIndex = stack[top - 1];
            top--;
            // 雨水形成的情况是凹的, 需要当前新的栈顶元素, 计算的是旧的栈顶元素形成的雨水
            if (top > 0) {
                int leftIndex = stack[top - 1];
                sum += (minFun(height[leftIndex], height[i]) - height[midIndex]) * (i - leftIndex - 1);
            }
        }
        stack[top] = i;
        top++;
    }

    return sum;
}
双指针

双指针解法:【竖向计算每个柱体形成的雨水】
两次遍历求当前左侧最高柱子高度maxLeft[i]和右侧最高柱子高度maxRight[i]

// 双指针解法:两次遍历求当前左侧最高柱子高度maxLeft[i]和右侧最高柱子高度maxRight[i]

int maxFun(int p1, int p2)
{
    return p1 > p2 ? p1 : p2;
}

int minFun(int p1, int p2)
{
    return p1 < p2 ? p1 : p2;
}

int trap(int* height, int heightSize) {
    int maxLeft[heightSize];
    int maxRight[heightSize];

    // 遍历搜索左侧最高柱子高度
    maxLeft[0] = height[0];
    for (int i = 1; i < heightSize; i++) {
        maxLeft[i] = maxFun(height[i], maxLeft[i - 1]);
    }

    // 遍历搜索右侧最高柱子高度
    maxRight[heightSize - 1] = height[heightSize - 1];
    for (int j = heightSize - 2; j >= 0; j--) {
        maxRight[j] = maxFun(height[j], maxRight[j + 1]);
    }

    // 遍历计算每个柱子接到的雨水之和
    int sum = 0;
    for (int k = 0; k < heightSize; k++) {
        sum += minFun(maxLeft[k], maxRight[k]) - height[k];
    }

    return sum;
}

[84] 柱状图中最大的矩形

题目描述

84 柱状图中最大的矩形
84 柱状图中最大的矩形

解题思路

前提:柱状图形成的最大面积,需要求解该柱子左右两侧 最远>=该柱子高度的柱子宽度,即可以求解该柱子左右两侧小于该柱子高度的位置,进而计算所求宽度
思路:单调递减栈
重点:单调栈的思维

代码实现

C语言
单调递减栈
// 单调递减栈: 寻找该柱子左右两侧第一个小于该柱子高度的柱子, 即可找到最后左右两侧最远一个大于该柱子高度的连续柱子, 计算所形成的的最大面积
// 栈顶到栈底,元素依次递减

int minFun(int p1, int p2)
{
    return p1 < p2 ? p1 : p2;
}

int maxFun(int p1, int p2)
{
    return p1 > p2 ? p1 : p2;
}

int largestRectangleArea(int* heights, int heightsSize) {
    int stack[heightsSize];
    int top = 0;
    int maxSum = 0;

    // 遍历
    for (int i = 0; i < heightsSize; i++) {
        // 寻找查找栈顶柱子的右侧第一个低于栈顶柱子的柱子位置
        while (top > 0 && heights[i] < heights[stack[top - 1]]) {
            // 弹出栈顶元素
            int midIndex = stack[top - 1];
            top--;
            // 计算弹出元素所形成的凸型的面积
            // 判断是否形成凸的最左侧
            int leftIndex = 0;
            if (top > 0) {
                leftIndex = stack[top - 1] + 1;
            }
            int rightIndex = i - 1;
            int sum = heights[midIndex] * (rightIndex - leftIndex + 1);
            maxSum = maxFun(maxSum, sum);
        }
        stack[top] = i;
        top++;
    }
    // 判断是否最后没有形成凸的最右侧,清空栈
    while (top > 0)
    {
        int midIndex = stack[top - 1];
        top--;
        if (top == 0) {
            // 此时这个元素为当前元素数组中最小的元素
            int sum = heights[midIndex] * heightsSize;
            maxSum = maxFun(maxSum, sum);
        } else {
            // 此时单调栈中元素递减
            int sum = heights[midIndex] * ((heightsSize - 1) - (stack[top - 1] + 1) + 1);
            maxSum = maxFun(maxSum, sum);
        }
    }
    
    return maxSum;
}

针对数组单调递增等不能形成凸型的特殊情况, 需要特殊处理,
所以在原数组首尾添加最小元素0, 以便对原数组做同一处理。
优化代码如下。

// 单调递减栈: 寻找该柱子左右两侧第一个小于该柱子高度的柱子, 即可找到最后左右两侧最远一个大于该柱子高度的连续柱子, 计算所形成的的最大面积
// 栈顶到栈底,元素依次递减
// 针对数组单调递增等的特殊情况, 需要特殊处理,所以在原数组首尾添加最小元素0,以便对原数组做同一处理

int maxFun(int p1, int p2)
{
    return p1 > p2 ? p1 : p2;
}

int largestRectangleArea(int* heights, int heightsSize) {
    int newHeightsSize = heightsSize + 2;
    int newHeights[newHeightsSize];
    newHeights[0] = 0;
    newHeights[newHeightsSize - 1] = 0;
    for (int t = 1; t < newHeightsSize - 1; t++) {
        newHeights[t] = heights[t - 1];
    }

    int stack[newHeightsSize];
    int top = 0;
    int maxSum = 0;

    // 遍历
    for (int i = 0; i < newHeightsSize; i++) {
        // 寻找查找栈顶柱子的右侧第一个低于栈顶柱子的柱子位置
        // 当遍历到新数组的最后一个元素0, 必可以进入该循环进行处理
        while (top > 0 && newHeights[i] < newHeights[stack[top - 1]]) {
            // 弹出栈顶元素
            int midIndex = stack[top - 1];
            top--;
            // 计算弹出元素所形成的凹型的面积
            // 此处的栈中必有新数组的首元素0
            int leftIndex = stack[top - 1] + 1;
            int rightIndex = i - 1;
            int sum = newHeights[midIndex] * (rightIndex - leftIndex + 1);
            maxSum = maxFun(maxSum, sum);
        }
        stack[top] = i;
        top++;
    }
    
    return maxSum;
}
双指针

寻找该柱子左侧的第一个小于该柱子的高度的下标minLeftIndex[i] 和 右侧第一个小于该柱子的高度的下标minRightIndex[i],
进而计算不小于该柱子高度的连续长度。

// 双指针方法: 寻找该柱子左侧的第一个小于该柱子的高度的下标minLeftIndex[i] 和 右侧第一个小于该柱子的高度的下标minRightIndex[i]
// 计算以当前柱子形成凹形状的柱子的最大面积

int minFun(int p1, int p2)
{
    return p1 < p2 ? p1 : p2;
}

int maxFun(int p1, int p2)
{
    return p1 > p2 ? p1 : p2;
}

int largestRectangleArea(int* heights, int heightsSize) {
    int minLeftIndex[heightsSize];
    int minRightIndex[heightsSize];

    // 遍历,寻找该柱子左侧的第一个小于该柱子的高度的下标
    minLeftIndex[0] = -1;
    for (int i = 1; i < heightsSize; i++) {
        int t = i - 1;
        // 查找左侧第一个小于该柱子高度的柱子下标
        while (t >= 0 && heights[t] >= heights[i]) {
            t = minLeftIndex[t];
        }
        minLeftIndex[i] = t;
    }

    // 遍历,寻找该柱子右侧的第一个小于该柱子的高度的下标
    minRightIndex[heightsSize - 1] = heightsSize;
    for (int j = heightsSize - 2; j >= 0; j--) {
        int t = j + 1;
        // 查找右侧第一个小于该柱子高度的柱子下标
        while (t < heightsSize && heights[t] >= heights[j]) {
            t = minRightIndex[t];
        }
        minRightIndex[j] = t;
    }

    // 遍历寻找最大面积
    int sum = 0;
    int maxSum = 0;
    for (int k = 0; k < heightsSize; k++) {
        // 求以当前柱子形成凹形状的柱子的最大面积
        int leftIndex = minLeftIndex[k] + 1;
        int rightIndex = minRightIndex[k] - 1;
        sum = heights[k] * (rightIndex - leftIndex + 1);
        maxSum = maxFun(maxSum, sum);
    }

    return maxSum;
}

今日收获

  1. 单调栈,以及为了使用单调栈所做的变化

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AI】DeepStream(14):图像分割deepstream-segmentation-test示例演示

【AI】AI学习目录汇总 1、简介 deepstream-segmentation-test示例演示了图像的语义分割。两个配置文件,分别加载U-Net和Res-UNet两种分割模型 unet_output_graph.uffunetres18_v4_pruned0.65_800_data.uffU-Net是一个在生物医学图像分割领域广泛应用的卷积神经网络(CNN),…

中国东方资产管理25届秋招北森测评笔试如何高分通过?真题考点分析看完这篇就够了

一、东方资管校招测评题型分析 中国东方资产管理股份有限公司&#xff08;中国东方资管&#xff09;的校园招聘测评题型主要包括以下几个部分&#xff1a; 1. **计分题&#xff0c;行测知识**&#xff1a;这部分题量大约在56-57题左右&#xff0c;分为不同的模块进行计时测试。…

【高阶数据结构】图的应用--最短路径算法

文章目录 一、最短路径二、单源最短路径--Dijkstra算法三、单源最短路径--Bellman-Ford算法四、多源最短路径--Floyd-Warshall算法 一、最短路径 最短路径问题&#xff1a;从在带权有向图G中的某一顶点出发&#xff0c;找出一条通往另一顶点的最短路径&#xff0c;最短也就是沿…

14个最佳创业企业WordPress主题

您网站的设计使您能够展示产品的独特卖点。通过正确的主题&#xff0c;您将能够解释为什么客户应该选择您的品牌而不是其他品牌。 在本文中&#xff0c;我们将向您介绍14个初创企业WordPress主题。我们将告诉您每个主题的独特之处以及哪些人应该考虑使用它。让我们开始吧&…

Pinia:Vue 2 和 Vue 3 中更好用的状态管理框架

前言 还在用Vuex? 在Vue应用程序的开发过程中&#xff0c;高效且易于维护的状态管理一直是开发者关注的核心问题之一。随着Vue 3的发布&#xff0c;状态管理领域迎来了一位新星——Pinia&#xff0c;它不仅为Vue 3量身打造&#xff0c;同时也向下兼容Vue 2&#xff0c;以其简…

Django学习第四天

启动项目命令 python manage.py runserver 分页功能封装到类中去 封装的类的代码 """ 自定义的分页组件,以后如果想要使用这个分页组件&#xff0c;你需要做&#xff1a; def pretty_list(request):# 靓号列表data_dict {}search_data request.GET.get(q, &…

谷粒商城-个人笔记(集群部署篇二)

前言 ​学习视频&#xff1a;​Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强​学习文档&#xff1a; 谷粒商城-个人笔记(基础篇一)谷粒商城-个人笔记(基础篇二)谷粒商城-个人笔记(基础篇三)谷粒商城-个人笔记(高级篇一)谷粒商城-个…

Excel为数据绘制拆线图,并将均值线叠加在图上,以及整个过程的区域录屏python脚本

Excel为数据绘制拆线图,并将均值线叠加在图上,以及整个过程的区域录屏python脚本 1.演示动画A.视频B.gif动画 2.跟踪鼠标区域的录屏脚本 Excel中有一组数据,希望画出曲线,并且能把均值线也绘制在图上,以下动画演示了整个过程,并且提供了区域录屏脚本,原理如下: 为节约空间,避免…

SpringBoot 启动流程一

SpringBoot启动流程一 我们首先创建一个新的springboot工程 我们不添加任何依赖 查看一下pom文件 我们创建一个文本文档 记录我们的工作流程 我们需要的是通过打断点实现 我们首先看一下启动响应类 package com.bigdata1421.start_up;import org.springframework.boot.Spr…

【Android面试八股文】Android性能优化面试题:怎样检测函数执行是否卡顿?

文章目录 卡顿一、可重现的卡顿二、不可重现的卡顿第一种方案: 基于 Looper 的监控方法第二种方案:基于 Choreographer 的监控方法第三种方案:字节码插桩方式第四种方案: 使用 JVMTI 监听函数进入与退出总结相关大厂的方案ArgusAPMBlockCanaryQQ空间卡慢组件Matrix微信广研参…

linux中与网络有关的命令

本文的命令总览 ifconfig命令 在 Linux 系统中&#xff0c;ifconfig 命令用于配置和显示网络接口的信息&#xff0c;包括 IP 地址、MAC 地址、网络状态等。同时我们也可以利用ifconfig 命令设置网络接口对应的ip地址&#xff0c;子网掩码等 当你使用 ifconfig 命令时&#xf…

DC/AC电源模块为现代电子设备提供稳定的能源

BOSHIDA DC/AC电源模块为现代电子设备提供稳定的能源 DC/AC电源模块是一种重要的电子设备&#xff0c;它为现代电子设备提供稳定的能源。在今天的高科技社会中&#xff0c;电子设备已经成为人们生活和工作的重要组成部分。从家用电器到计算机、手机、汽车和航天航空设备&…

微信小程序毕业设计-球馆预约系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

Spring AI 1.0.0 新变化,从 0.8.1 如何升级

Spring AI 1.0.0-M1 版本已经发布&#xff0c;距离 1.0.0 正式版又更近了一步。同时这也意味着&#xff0c;Spring AI 1.0.0 的 API 已经基本确定&#xff0c;不会发生大的改动。这里介绍一下&#xff0c;相对于上一个发布版本 0.8.1&#xff0c;Spring AI 1.0.0 的一些重要的变…

【C语言】—— 文件操作(上)

【C语言】—— 文件操作&#xff08;上&#xff09; 一、 为什么使用文件二、 什么是文件2.1、 程序文件2.2、 数据文件2.3、 文件名2.4、二进制文件与文本文件 三、 文件的打开和关闭3.1、流和标准流&#xff08;1&#xff09;流&#xff08;2&#xff09;标准流 3.2、文件指针…

@PostConstruct注解

1.简介 PostConstruct是java5的时候引入的注解&#xff0c;主要用于标记一个方法&#xff0c;表示该方法应在依赖注入完成后自动调用。通常在使用Java EE或者Spring框架时使用这个注解&#xff0c;以便在Bean初始化之后执行一些初始化工作&#xff0c; 可作为一些数据的常规化…

hadoop集群部署【二】YARN MapReduce 的部署

提前注意&#xff1a;请注意路径是否和我的相同&#xff0c;放置的位置不同&#xff0c;请修改标红处 HDFS部署 HDFS介绍及部署http://t.csdnimg.cn/Q3H3Y 部署说明 Hadoop HDFS分布式文件系统&#xff0c;我们会启动&#xff1a; NameNode进程作为管理节点 DataNode进程…

WRF学习——使用CMIP6数据驱动WRF/基于ncl与vdo的CMIP6数据处理

动力降尺度 国际耦合模式比较计划&#xff08;CMIP&#xff09;为研究不同情景下的气候变化提供了大量的模拟数据&#xff0c;而在实际研究中&#xff0c;全球气候模式输出的数据空间分辨率往往较低&#xff08;>100Km&#xff0c;缺乏区域气候特征&#xff0c;为了更好地研…

K8s 集群(kubeadm) CA 证书过期解决方案

Author&#xff1a;Arsen Date&#xff1a;2024/07/04 目录 一、现象描述二、解决方案三、集群验证 一、现象描述 之前有篇文章《K8s Token 过期解决方案&#xff08;Kubeadm&#xff09;》提到了默认生成的 Token 有效期只有 24 小时&#xff0c;过期后 Token 将不可用&#…

C# 类型转换之显式和隐式

文章目录 1、显式类型转换2. 隐式类型转换3. 示例4. 类型转换的注意事项5. 类型转换的应用示例总结 在C#编程中&#xff0c;类型转换是一个核心概念&#xff0c;它允许我们在程序中处理不同类型的数据。类型转换可以分为两大类&#xff1a;显式类型转换&#xff08;Explicit Ca…