【刷题笔记】接雨水||暴力通过||符合思维方式

news2024/11/29 2:45:13

接雨水

文章目录

  • 接雨水
    • 1 题目描述
    • 2 分析
      • 2.1 左到右
      • 2.2 右到左
      • 2.3 计算面积
    • 3 代码
      • 3.1 Java
      • 3.2 Python
    • 附录1

1 题目描述

https://leetcode.cn/problems/trapping-rain-water/

面试的时候关键不是你的手法多么精妙,首先要做出来。

在这里插入图片描述

给定 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


2 分析

通过观察,我们知道,要计算接的水,我们要找到能够存水的凹槽:

我们将这些存水的凹槽的边缘连接起来,可以发现,折线图的总体趋势是从低到高,从高到低(下图是随机生成的不同高度下的存水凹槽边缘图,以及其连线)

在这里插入图片描述

绘图代码已经在附录1中给出,可以直接运行,随机生成数据以及查看绘图。

那么我们能做的就是从左到右,依次找到越来越高的值;保存其索引,从右到左,依次找到越来越高的值,保存其索引。然后计算这些索引之间的最大盛水面积,减去之间的柱子的面积,就是最后的接雨水的结果
在这里插入图片描述

2.1 左到右

while start < len(height) and height[start] == 0: # 指针不断右移,跳过为0的元素
    start = start + 1
if start >= len(height) - 1: # 要是全为0,return 0
    return 0
lists.append(height[start]) # 保存值
indexes.append(start) # 保存索引
for i in range(start + 1, len(height)):
    if height[i] >= lists[-1]: # 比上一个凹槽边缘大或者等于,保存
        lists.append(height[i])
        indexes.append(i)

2.2 右到左

# 注意从右到左,不要超过左到右的边界indexes[-1],
 while end > indexes[-1] and height[end] == 0: 
        end = end - 1 
# 而且从左到右已经判断完全0了,接下来不用判断了
reverse_lists.append(height[end])
reverse_indexes.append(end)
for i in range(end - 1, indexes[-1] - 1, -1): # 从右到左,注意边界
# 注意range(end - 1, indexes[-1] - 1, -1),举个例子,如果要生成一个10~0的
# 序列,则为range(10, -1, -1),我们知道range的前两个参数为范围,前闭后开,[10,-1)
# 第二个-1为step,表示按照反向遍历。
    if height[i] >= reverse_lists[-1]:
        reverse_lists.append(height[i])
        reverse_indexes.append(i)

2.3 计算面积

最直接的想法是,直接分开计算面积:
在这里插入图片描述

l_res = 0
for i in range(1, len(lists)):
    l = indexes[i - 1]
    r = indexes[i]
    l_res = l_res + (r - l - 1) * (min(height[l], height[r])) # 高度最小值乘以长度,
    # 长度为(right - left - 1)
    for j in range(l + 1, r):
        l_res = l_res - height[j] # 减去中间的面积

for i in range(len(reverse_indexes) - 2, -1, -1): # 反过来遍历
    r = reverse_indexes[i]
    l = reverse_indexes[i + 1]
    l_res = l_res + (r - l - 1) * (min(height[l], height[r]))
    for j in range(l + 1, r):
        l_res = l_res - height[j]
return l_res

为了简单计算,首先我们将两个索引合并,

l_res = 0
# 将indexes和reversed(reverse_indexes)合并
indexes.extend(reversed(reverse_indexes))

在上面的图中,我们看到,两边的索引(左到右:[0, 3, 5],右到左:[19, 16, 11, 7, 5])有重叠,合并以后变成了[0, 3, 5, 5, 7, 11, 16, 19]怎么办?

无所谓,重叠之后长度为0,二者之间的面积还是0,不会对最终的面积有啥影响。

那么最后计算面积的过程为:

for i in range(1, len(indexes)):
    l = indexes[i - 1]
    r = indexes[i]
    l_res = l_res + max((r - l - 1), 0) * (min(height[l], height[r]))
    for j in range(l + 1, r):
        l_res = l_res - height[j]
return l_res

3 代码

3.1 Java

class Solution {

    public int trap(int[] height) {

        if (height.length <= 1) return 0;

        List<Integer> lists = new ArrayList<>();
        List<Integer> indexes = new ArrayList<>();

        List<Integer> reverse_lists = new ArrayList<>();
        List<Integer> reverse_indexes = new ArrayList<>();
        int start = 0;
        int end = height.length - 1;
        while(start < height.length && height[start] == 0) start++;
        if (start >= height.length - 1) return 0;
        lists.add(height[start]);
        indexes.add(start);

        for (int i = start + 1; i < height.length; i++) {
            if (height[i] >= lists.get(lists.size() - 1)) {
                lists.add(height[i]);
                indexes.add(i);
            }
        }
        int l_res = 0;
        for (int i = 1; i < lists.size(); i++) {
            int l = indexes.get(i - 1);
            int r = indexes.get(i);
            l_res += (r - l - 1) * (Math.min(height[l], height[r]));
            for (int j = l + 1; j < r; j++) {
                l_res -= height[j];
            }
        }


        while(end > indexes.get(indexes.size() - 1) && height[end] == 0) end--;
        reverse_lists.add(height[end]);
        reverse_indexes.add(end);
        for (int i = end - 1; i >= indexes.get(indexes.size() - 1); i--) {
            if (height[i] >= reverse_lists.get(reverse_lists.size() - 1)) {
                reverse_lists.add(height[i]);
                reverse_indexes.add(i);
            }
        }

        for (int i = reverse_indexes.size() - 2; i >=0; i--) {
            int r = reverse_indexes.get(i);
            int l = reverse_indexes.get(i + 1);
            l_res += (r - l - 1) * (Math.min(height[l], height[r]));
            for (int j = l + 1; j < r; j++) {
                l_res -= height[j];
            }
        }
        return l_res;

    }
}

3.2 Python

class Solution(object):

    # python 代码
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        if len(height) <= 1:
            return 0
        lists = []
        indexes = []
        reverse_lists = []
        reverse_indexes = []
        start = 0
        end = len(height) - 1
        while start < len(height) and height[start] == 0:
            start = start + 1
        if start >= len(height) - 1:
            return 0
        lists.append(height[start])
        indexes.append(start)
        for i in range(start + 1, len(height)):
            if height[i] >= lists[-1]:
                lists.append(height[i])
                indexes.append(i)
        while end > indexes[-1] and height[end] == 0:
            end = end - 1
        reverse_lists.append(height[end])
        reverse_indexes.append(end)
        for i in range(end - 1, indexes[-1] - 1, -1):
            if height[i] >= reverse_lists[-1]:
                reverse_lists.append(height[i])
                reverse_indexes.append(i)
        l_res = 0
        # 将indexes和reversed(reverse_indexes)合并
        indexes.extend(reversed(reverse_indexes))
        for i in range(1, len(indexes)):
            l = indexes[i - 1]
            r = indexes[i]
            l_res = l_res + max((r - l - 1), 0) * (min(height[l], height[r]))
            for j in range(l + 1, r):
                l_res = l_res - height[j]
        return l_res

在这里插入图片描述

附录1

# python 代码
def trap(height):
    """
    :type height: List[int]
    :rtype: int
    """
    if len(height) <= 1:
        return 0
    lists = []
    indexes = []
    reverse_lists = []
    reverse_indexes = []
    start = 0
    end = len(height) - 1
    while start < len(height) and height[start] == 0:
        start = start + 1
    if start >= len(height) - 1:
        return 0
    lists.append(height[start])
    indexes.append(start)
    for i in range(start + 1, len(height)):
        if height[i] >= lists[-1]:
            lists.append(height[i])
            indexes.append(i)
    while end > indexes[-1] and height[end] == 0:
        end = end - 1
    reverse_lists.append(height[end])
    reverse_indexes.append(end)
    for i in range(end - 1, indexes[-1] - 1, -1):
        if height[i] >= reverse_lists[-1]:
            reverse_lists.append(height[i])
            reverse_indexes.append(i)
    l_res = 0
    # 将indexes和reversed(reverse_indexes)合并
    history_indexes = indexes.copy()
    indexes.extend(reversed(reverse_indexes))
    for i in range(1, len(indexes)):
        l = indexes[i - 1]
        r = indexes[i]
        l_res = l_res + max((r - l - 1), 0) * (min(height[l], height[r]))
        for j in range(l + 1, r):
            l_res = l_res - height[j]
    return l_res, history_indexes, reverse_indexes


def draw_pic(water, indexes, reverse_indexes):
    indexes.extend(reverse_indexes)
    indexes = list(set(indexes))
    indexes.sort()
    # 绘制折线图,x轴为indexes,y轴为water[indexes]
    plt.plot(indexes, [water[i] for i in indexes])
    plt.scatter(indexes, [water[i] for i in indexes])

    # 将water绘制成柱状图
    plt.bar(range(len(water)), water, color='yellow', zorder=1, edgecolor='black', linewidth=1)
    # 将indexes绘制成柱状图,绿色
    plt.bar(indexes, [water[i] for i in indexes], color='g', zorder=100, edgecolor='black', linewidth=1)
    # 设置 x 轴刻度及标签
    plt.xticks(np.arange(0, 20), range(0, 20))
    plt.show()

# 生成一个更长的测试用例
import random
random.randint(0, 10)
water = [random.randint(0, 10) for _ in range(20)]

res = trap(water)
indexes = res[1]
reverse_indexes = res[2]
draw_pic(water, indexes, reverse_indexes)

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

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

相关文章

Redis之C语言底层数据结构笔记

目录 动态字符串SDS Dict ZipList QuickList ​ SkipList 动态字符串SDS Dict ZipList QuickList SkipList

汇编实验2-2 查找匹配字符串笔记

一、数据段 1.字符串结尾&#xff1a;13,10&#xff0c;$ 2.设置格式控制字符串(这样就不用再写clrf函数了) 3.设置存关键字和句子的地址标签&#xff0c;以关键字为例 二、代码段 1.输入字符串 2.字符串比较 2.1 每次的比较长度&#xff0c;KLEN->CL 2.2 设置目标串起始…

代码随想录算法训练营第五十九天|503. 下一个更大元素 II、42. 接雨水

第十章 单调栈part02 503. 下一个更大元素 II 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之…

应用程序安装异常(-113)

应用程序安装异常(-113) 报错如下&#xff1a;    应用未安装:应用与您的手机不兼容。    应用程序安装异常(-113)    这种情况是说我们的是x86架构&#xff0c;但是你运行的项目支持的是arm架构&#xff0c;所以你需要让自己的项目也支持arm的架构。 方案一 在项目的…

【Seata源码学习 】篇五 注册分支事务

【Seata源码学习 】篇五 分支事务注册 1.远程服务调用绑定XID 回到事务模版方法类TransactionalTemplate中 beginTransaction(txInfo, tx);Object rs;try {// Do Your Business// 执行执行拦截器链路rs business.execute();} catch (Throwable ex) {// 3. The needed busine…

人力资源管理后台 === 上传+权限数据

目录 1.员工详情-封装员工头像组件 2.员工详情-上传图片-创建腾讯云存储桶 3.员工详情-使用cos-sdk完成上传 4. 权限管理-搭建权限页面 5.权限管理-获取数据转化树形 6.权限管理-作业 7.权限应用-权限概念 8.权限应用-员工分配角色-弹出层 9.权限应用-员工分配角色-回…

运维 | 浅谈云计算的相关概念和分类

关注&#xff1a;CodingTechWork 云计算 云计算的出现 云计算是采用的按需付费的方式&#xff0c;通过互联网访问云服务器上的服务器、数据库等服务。云计算为何会出现&#xff1f;  如果现在一个企业想要进行软件管理部署&#xff0c;首先需要服务器主机和网络规划&#…

自建CA实战之 《0x01 Nginx 配置 https单向认证》

自建私有化证书颁发机构&#xff08;Certificate Authority&#xff0c;CA&#xff09;实战之 《0x01 Nginx 配置 https单向认证》 上一篇文章我们介绍了如何自建私有化证书颁发机构&#xff08;Certificate Authority&#xff0c;CA&#xff09;&#xff0c;本篇文章我们将介…

OSG粒子系统与阴影 - ​​​​​​​粒子系统的读取与保存(6)

粒子系统的读取与保存 在前面的章节中&#xff0c;已经讲到了所有的粒子系统的基本使用方法和自定义粒子系统的方法。有时需要把一个好的粒子系统保存起来&#xff0c;方便以后使用。保存粒子系统可以通过简单地调用 osgDB::writeNodeFile()来完成&#xff0c;如果直接读取并加…

高性能Mysql第三版(一)

学习目标&#xff1a; 高性能Mysql第3版 学习内容&#xff1a; MySQL架构与历史Mysql基座测试服务器性能Schema与数据类型优化创建高性能的索引查询性能优化Mysql高级特性Explain 文章目录 学习目标&#xff1a;高性能Mysql第3版 学习内容&#xff1a;1 Mysql逻辑架构1.1 My…

【STM32单片机】贪吃蛇游戏设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用STM32F103C8T6单片机控制器&#xff0c;使用8*8LED点阵模块、矩阵按键、蜂鸣器模块等。 主要功能&#xff1a; 系统运行后&#xff0c;贪吃蛇游戏开始运行&#xff0c;默认蛇身为2节&#xff…

057-第三代软件开发-文件监视器

第三代软件开发-文件监视器 文章目录 第三代软件开发-文件监视器项目介绍文件监视器实现原理关于 QFileSystemWatcher实现代码 关键字&#xff1a; Qt、 Qml、 关键字3、 关键字4、 关键字5 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&…

【数据结构初阶】树,二叉树

树&#xff0c;二叉树 1.树概念及结构1.1树的概念1.2 树的相关概念1.3 树的表示1.4 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 2.二叉树概念及结构2.1概念2.2现实中的二叉树2.3 特殊的二叉树2.4 二叉树的性质2.5 二叉树的存储结构 1.树概念及结构 1.…

计算机视觉算法——基于Transformer的目标检测(DN DETR / DINO / Sparser DETR / Lite DETR)

计算机视觉算法——基于Transformer的目标检测&#xff08;DN DETR / DINO&#xff09; 计算机视觉算法——基于Transformer的目标检测&#xff08;DN DETR / DINO&#xff09;1. DN DETR1.1 Stablize Hungarian Matching1.2 Denoising1.3 Attention Mask 2. DINO2.1 Contrasti…

Map和Set小总结【温习】

目录 一、概念与模型 二、Map的使用 三、Set的说明 一些小练习 四、哈希表 1.概念 2.冲突 2.1、概念 2.2、冲突-->避免 2.3、冲突-->解决 &#xff08;1&#xff09;闭散列 &#xff08;2&#xff09;开散列 2.4、其他问题 一、概念与模型 1.概念&#xff1a…

全程云OA SQL注入漏洞复现

0x01 产品简介 全程云OA为企业提供日常办公管理、公文管理、工作请示、汇报、档案、知识体系、预算控制等26个功能&#xff0c;超过100多个子模块。为企业内部提供高效、畅通的信息渠道&#xff0c;同时也能大力推动公司信息系统发展&#xff0c;提高企业的办公自动化程度和综合…

wangeditor实时预览

<template><div><!--挂载富文本编辑器--><div style"width: 45%;float: left;margin-left: 2%"><p>编辑内容</p><div id"editor" style"height: 100%"></div></div><div style"w…

基于halo框架采用docker-compose快速部署个人博客

halo快速部署个人博客 技术方案 dockerdocker-composenginxmysql halo简介 Halo是一款现代化的开源博客/CMS系统&#xff0c;所有代码开源在GitHub上且处于积极维护状态。它是基于 Java Spring Boot 构建的&#xff0c;易于部署&#xff0c;支持REST API、模板系统、附件系…

二叉树算法—后继节点

与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 1 后继节点1.1 解题思路1.2 代码实现 &#x1f48e;总结 1 后继节点 1.1 解题思路 二叉树节点结构定义如下&#xff1a; public static class Node { public int cal; public Node left; public Node right; public…

记一次处理大数据而导致的内存溢出问题

问题 订单服务通过MQ进行订单同步时&#xff0c;刚启动可以正常消费&#xff0c;但是跑一会就会卡住&#xff0c;每次都是第8个kafka分区不行再进行消费&#xff0c;其他分区消费的很慢。 现象 首先&#xff0c;CPU超高&#xff0c;达到百分之300多&#xff1b;其次&#xf…