1. 问题背景与核心挑战
这道LeetCode经典题目"接雨水"看似简单,却蕴含着精妙的算法思想。题目给定n个非负整数表示的高度图,每个柱子的宽度为1,计算下雨后这个排列能接多少雨水。举个生活化的例子,就像在凹凸不平的屋顶摆放一排宽度相同的花盆,雨后计算这些花盆之间能存住多少水。
新手最容易陷入的误区是只关注局部凹陷。比如看到三个柱子[3,1,2]就认为1的位置能存1单位水,实际上右边2比1高但比3矮,最终只能存(3-2)=1单位水。全局视角的缺失会导致计算错误,这正是问题的精妙之处。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 暴力解法与优化方向
最直观的暴力解法是对每个柱子,找到其左右两侧的最高柱子,取较小值减去当前柱子高度。时间复杂度O(n²),空间复杂度O(1)。这在LeetCode上会超时,但能帮助我们理解问题本质:
java复制int trap(int[] height) {
int res = 0;
for (int i = 1; i < height.length - 1; i++) {
int leftMax = 0, rightMax = 0;
// 向左找最高
for (int j = i; j >= 0; j--)
leftMax = Math.max(leftMax, height[j]);
// 向右找最高
for (int j = i; j < height.length; j++)
rightMax = Math.max(rightMax, height[j]);
res += Math.min(leftMax, rightMax) - height[i];
}
return res;
}
观察发现暴力解法中有大量重复计算——每个位置都在反复查询左右最大值。很自然想到可以用预处理数组存储这些值,这正是双指针解法的基础。
3. 预处理数组解法详解
预处理解法通过两次遍历,提前计算好每个位置的左右最大值:
java复制int trap(int[] height) {
if (height == null || height.length ==
