[Leetcode 之 PHP 解析 (42. Trapping Rain Water)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: [Leetcode 之 PHP 解析 (42. Trapping Rain Water)

1668569051540.jpg

题目介绍


这道题挺有意思的,给定一个非负数的每个宽度为 1 的柱形图,问你下雨天能接多少雨水。例题中给定的数组能接的总数为 6,即图中蓝色部分。


题目分析


我们先来随便举个例子吧。例如示例中给出的数组第 6 位(也就是索引位置 5)高度为 0,此时这个位置能盛的水是 2。这个 2 是咋么算出来的呢。从当前位置往它的左边查找,查出最高的水位,即索引 3 (值为 2)。从当前位置往右边找出它的最高位,即索引位置 7 (值为 3),然后取他们中的最小值高度 min (2,3) 减去当前位置的高度 (0)=2。为什么取的是两者的最小值呢。很简单的道理,两边之间能盛的水的高度必然会和其中一边高度持平的,再高就溢出了。


代码实现


/**
 * @param Integer[] $height
 * @return Integer
 */
function trap($height)
{
    $res = 0;
    $size = count($height);
    for ($i = 1; $i < $size - 1; $i++) {
        $left = 0;
        $right = 0;
        for ($j = $i; $j >= 0; $j--) {
            $left = max($left, $height[$j]);
        }
        for ($j = $i; $j < $size; $j++) {
            $right = max($right, $height[$j]);
        }
        $res += min($left, $right) - $height[$i];
    }
    return $res;
}

你应该已经发现了,上面的执行时间是 O (n*n)。每一个位置我们都遍历查找了左右两边,仅仅是为了找最大值,我们为什么不把每个位置左右两边最大值一次存起来?


/**
 * @param Integer[] $height
 * @return Integer
 */
function trap($height)
{
    $res = 0;
    $size = count($height);
    $left[0] = $height[0];
    for ($i = 1; $i < $size; $i++) {
        $left[$i] = max($left[$i - 1], $height[$i]);
    }
    $right[$size - 1] = $height[$size - 1];
    for ($i = $size - 2; $i >= 0; $i--) {
        $right[$i] = max($right[$i + 1], $height[$i]);
    }
    for ($i = 1; $i < $size - 1; $i++) {
        $res += min($left[$i], $right[$i]) - $height[$i];
    }
    return $res;
}

其实上面的解题思路就是一个动态规划的过程。动态规划最重要的两步:1 是状态的定义,即上面的这两个定义:

$left[0] = $height[0];
$right[$size - 1] = $height[$size - 1];

第二步就是状态转移方程,即上面的

$left[$i] = max($left[$i - 1], $height[$i]);
 $right[$i] = max($right[$i + 1], $height[$i]);

其实动态规划就像是开启了上帝的视角,每次都能获取到全局的情况。经常用来解最优,最近,最少这类题目。你再进一步分析,好像动态规划的思想就是一个空间换时间的方案。第一个解的时间是 O (n 的平方),空间就一个变量 O (1)。再来看第二道解,时间是 O (n),空间是 O (n)。本质上来说就是空间换时间的方案。最后其实这道题还有其他能解的方案。。。。刷着刷着,乐趣就上来了。

相关文章
|
1月前
|
运维 数据库连接 PHP
PHP中的异常处理机制深度解析####
本文深入探讨了PHP中异常处理机制的工作原理,通过实例分析展示了如何有效地使用try-catch语句来捕获和处理运行时错误。我们将从基础概念出发,逐步深入到高级应用技巧,旨在帮助开发者更好地理解和利用这一强大的工具,以提高代码的稳定性和可维护性。 ####
|
1月前
|
PHP 开发者 UED
PHP中的异常处理机制解析####
本文深入探讨了PHP中的异常处理机制,通过实例解析try-catch语句的用法,并对比传统错误处理方式,揭示其在提升代码健壮性与可维护性方面的优势。文章还简要介绍了自定义异常类的创建及其应用场景,为开发者提供实用的技术参考。 ####
|
1月前
|
PHP 开发者 容器
PHP命名空间深度解析及其最佳实践####
本文深入探讨了PHP中引入命名空间的重要性与实用性,通过实例讲解了如何定义、使用及别名化命名空间,旨在帮助开发者有效避免代码冲突,提升项目的模块化与可维护性。同时,文章还涉及了PHP-FIG标准,引导读者遵循最佳实践,优化代码结构,促进团队协作效率。 ####
32 1
|
1月前
|
PHP 开发者 容器
PHP命名空间深度解析:避免命名冲突与提升代码组织####
本文深入探讨了PHP中命名空间的概念、用途及最佳实践,揭示其在解决全局命名冲突、提高代码可维护性方面的重要性。通过生动实例和详尽分析,本文将帮助开发者有效利用命名空间来优化大型项目结构,确保代码的清晰与高效。 ####
35 1
|
2月前
|
编译器 PHP 开发者
PHP 8新特性解析与实战应用####
随着PHP 8的发布,这一经典编程语言迎来了诸多令人瞩目的新特性和性能优化。本文将深入探讨PHP 8中的几个关键新功能,包括命名参数、JIT编译器、新的字符串处理函数以及错误处理改进等。通过实际代码示例,展示如何在现有项目中有效利用这些新特性来提升代码的可读性、维护性和执行效率。无论你是PHP新手还是经验丰富的开发者,本文都将为你提供实用的技术洞察和最佳实践指导。 ####
38 1
|
4月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
68 6
|
5月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
137 2
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
72 1
|
4月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口

推荐镜像

更多