微信公众号:编程笔记本
点击上方蓝字关注我,我们一起学编程
欢迎小伙伴们分享、转载、私信、赞赏
今天我们一起来探讨一道字节跳动的算法面试题——接雨水。
题目:有一组不同高度的台阶,由一个整数数组表示,数组中每个元素代表台阶的高度。当开始下雨了(雨水足够多),台阶之间的水坑会积多少水呢?如下图所示,可以表示为数组 [0,1,0,2,1,0,1,3,2,1,2,1] ,程序返回积水量 6 。
图片
这道题十分有趣,解法也很多样。主要有暴力法、记忆法、双指针法等几种,下面我们一一探讨。
一、暴力法
当我们一开始拿到题目的时候,可能并没有什么好的思路,那么这时候我们可以不去考虑整体的情况,可以先从局部下手。具体来说就是,仅仅针对位置 i ,此处能积多少水呢?
图片
很显然,位置 i 处能积 2 格水。为什么刚好能积 2 格水呢?原来,位置 i 的高度为 0 ,其左边最高的台阶为 2 ,右边最高的台阶为 3 ,根据木桶效应,此处最大的积水高度为 min(2, 3) - 0 。
图片
更一般地描述可以概括为下面的公式:
积水高度[i] = min(i左侧最高台阶, i右侧最高台阶) - 台阶高度[i];
也就是说,我们要计算出位置 i 的积水高度,就必须要知道位置 i 左侧的最高台阶高度和位置 i
右侧的最高台阶高度。分析到这里,暴力法就自然引出了,下面是参考代码:
int trap(vector<int>& height)
{
int ans = 0;
int n = height.size();
// 第一个台阶和最后一个台阶不会积水
for (int i = 1; i < n - 1; ++i)
{
int l_max = 0;
int r_max = 0;
// 右边最高高度
for (int j = i + 1; j < n; ++j)
{
if (height[j] > r_max)
{
r_max = height[j];
}
}
// 左边最高高度
for (