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

news2024/11/24 3:08:24

前言

思路及算法思维,指路 代码随想录。
题目来自 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. 单调栈,以及为了使用单调栈所做的变化

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

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

相关文章

Modbus协议转Profinet协议网关模块连智能仪表与PLC通讯

一、现场需求&#xff1a;PLC作为控制器&#xff0c;仪表设备做为执行设备&#xff0c;执行设备能够实时响应PLC传来的指令&#xff0c;并且向PLC回馈数据&#xff0c;从而达到PLC对仪表设备进行控制和监测&#xff0c;实现对生产过程的精准控制。 二、解决方案&#xff1a;通过…

机器学习与AI大数据的融合:开启智能新时代

在当今这个信息爆炸的时代&#xff0c;大数据和人工智能&#xff08;AI&#xff09;已经成为推动社会进步的强大引擎。作为AI核心技术之一的机器学习&#xff08;Machine Learning, ML&#xff09;&#xff0c;与大数据的深度融合正引领着一场前所未有的科技革命&#xff0c;不…

Java判断范围型的数据是否存在重叠(数值类型、日期类型)

为什么写这么一篇文章呢&#xff1f; 遇到了个问题&#xff0c;同一天可以输入多个时间段&#xff0c;但是每个时间段的时间不能出现重叠。 纳尼&#xff0c;这不就是判断数据返回是否有重叠的变种嘛~ 简单&#xff0c;开搞 数字范围是否重叠判断 这里以int类型为例了&…

高德地图轨迹回放并提示具体信息

先上效果图 到达某地点后显示提示语:比如:12:56分驶入康庄大道、左转驶入xx大道等 <!doctype html> <html> <head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta n…

基于Vue.js的电商前端模板:Vue-Dashboard-Template的设计与实现

摘要 随着电子商务的飞速发展&#xff0c;前端页面的设计和实现变得愈发重要。本文介绍了一个基于Vue.js的电商前端模板——Vue-Dashboard-Template&#xff0c;旨在提供一个高性能、易扩展的电商平台前端解决方案。该模板遵循响应式设计、模块化、组件化开发等设计原则&#…

预制菜工厂MES系统:具体功能与应用场景

在现代化食品工业中&#xff0c;预制菜&#xff08;Ready-to-Eat, RTE&#xff09;因其方便快捷、卫生安全及营养均衡的特点&#xff0c;迅速在餐饮行业中占据重要地位。为了进一步提升预制菜工厂的生产效率、保障产品质量并降低生产成本&#xff0c;制造执行系统&#xff08;M…

C# 快速排序算法的详细讲解

目录 一、前言 二、例子 三、快速排序算法图片讲解 四、快速排序算法代码 五、纯净代码 一、前言 用比较好懂的方式讲一下快速排序算法。 二、例子 如果我有一堆钱&#xff0c;想数清楚&#xff0c;最快的方案是什么&#xff1f; 图1 一堆钱 答&#xff1a;先分类&…

【Linux开发实战指南】基于TCP、进程数据结构与SQL数据库:构建在线云词典系统(含注册、登录、查询、历史记录管理功能及源码分享)

目录 项目演示&#xff1a; 1. 主界面 技术讲解&#xff1a; TCP连接 进程的并发 链表 SQLite3 IO对文件的读写 功能实现 实现逻辑 我遇到的问题&#xff1a; 服务器端代码思路解析 必要条件 步骤详解 客户端代码思路解析 步骤详解 服务器源码如下&#xff1a;…

GD32实战项目-app inventor-BLE低功耗DX-BT24蓝牙上位机制作-文末有关于生成的软件闪退或者卡死问题的解决

本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发 后续项目主要在下面该专栏中发布&#xff1a; 手把手教你嵌入式国产化_不及你的温柔的博客-CSDN博客 感兴趣的点个关注收藏一下吧! 电机驱动开发可以跳转&#xff1a; 手把手教你嵌入式国产化-实战项目-无刷电机驱动&am…

什么开放式耳机好用?五大王牌开放式耳机种草!

随着科技的持续进步&#xff0c;开放式蓝牙耳机悄然兴起&#xff0c;逐步取代了经典的入耳式耳机。入耳式耳机以其卓越的隔音性能著称&#xff0c;然而&#xff0c;长时间的使用却容易引发耳道受压&#xff0c;伴随而来的不仅是疼痛与不适&#xff0c;更潜藏着耳膜受损的风险。…

C++面试宝典30题丨第一题:开灯

专栏导读 见得题目越多&#xff0c;考试时抽中的概率也越大。每一题都有详细的解答思路和独有的视频讲解。 本文收录于&#xff1a;C面试宝典&#xff08;送视频讲解&#xff09; ☆☆☆购买专栏后&#xff0c;请加微信会私发讲解视频&#xff01; 题目描述 一条名叫Mango的街…

简过网:一建和二建的含金量,哪个难度更大一些?

你知道&#xff0c;一建和二建有什么区别吗&#xff0c;考哪个更合适自己呢&#xff1f;正在备考一建、二建的小伙伴们&#xff0c;这篇文章千万不要错过哦&#xff01; 首先&#xff0c;先说一下大家比较关注的含金量问题&#xff0c;一建含金量明显比二建高&#xff0c;但是…

MySQL篇-SQL优化实战-减少子查询

回顾 上一篇了解了分析SQL使用的explain&#xff0c;可以点击查看MySQL篇-SQL优化实战了解我在写sql的注意事项还有explain的说明&#xff0c;这次拿一段生产使用的sql进行优化说明。从14s优化到2.6s 待优化的SQL SELECT DISTINCTswpe.tag_number,hca.ACCOUNT_NAME customer…

精准定位推广盲点?Xinstall数据监测让每一分投入都见成效!

在这个数字化时代&#xff0c;App的推广早已不再是简单的“上线即成功”。面对激烈的市场竞争和日益挑剔的用户&#xff0c;如何精准监测推广数据&#xff0c;优化营销策略&#xff0c;成为了每个开发者与营销人员不得不面对的挑战。而在这个关键时刻&#xff0c;Xinstall作为一…

AI 驱动的数据中心变革与前景

文章主要探讨了AI计算时代数据中心的转型&#xff0c;涉及计算技术的多样性、规格尺寸和加速器的发展、大型语言模型&#xff08;LLM&#xff09;的发展、功耗和冷却趋势、基准测试的重要性以及数据中心的发展等方面。为大家提供深入了解AI基础设施发展的视角。 计算技术的多样…

Python 程序打印图案“G”(Python Program to print the pattern ‘G’)

在本文中&#xff0c;我们将学习如何使用星号和空格打印图案 G。给定一个数字 n&#xff0c;我们将编写一个程序&#xff0c;在 n 行或列上打印图案 G。 例子&#xff1a; 输入&#xff1a;7 输出&#xff1a; *** * * * *** * * * * *** 输入&…

红酒的秘密花园:探索葡萄的种植艺术

在远离城市喧嚣的某个角落&#xff0c;隐藏着一座神秘的红酒秘密花园。这里&#xff0c;葡萄藤缠绵交织&#xff0c;绿叶间闪烁着晶莹的露珠&#xff0c;仿佛在诉说着关于红酒与葡萄种植艺术的古老传说。今天&#xff0c;就让我们一起走进这片神秘的花园&#xff0c;探寻葡萄种…

@amap/amap-jsapi-loader 实现高德地图中添加多边围栏,并可编辑,编辑后获得围栏各个点的经纬度

先上一张效果图 看看是不是大家想要的效果&#xff5e; ❤️ 希望其中的小点能帮助大家&#xff0c;主要看怎么绘制在地图上的代码即可 1.第一步要加入项目package.json中或者直接yarn install它都可以 想必大家应该都会 "amap/amap-jsapi-loader": "0.0.7&qu…

Oracle EBS PO采购订单预审批状态处理

系统版本 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题症状: 采购订单状态:预审批 采购订单流程报错如下: po.plsql.PO_DOCUMENT_ACTION_AUTH.approve:90:archive_po not successful - po.plsql.PO_DOCUMENT_ACTION_PVT.do_action:110:unexpected error in acti…

Unity In App Purchasing内购校验

1&#xff0c;利用收据验证混淆器 把后台的key填进去&#xff0c;点击自动生成一些文件 2&#xff0c;代码过滤 using UnityEngine.Purchasing.Security;在IAPManager.cs的 public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)增加 #if !UNITY_EDITOR…