题目
解题
解题一:暴力解法
// javascript
var trap = function(height) {
const n = height.length;
let ans = 0;
for (let i = 1; i < n - 1; ++i) { // 第一和最后一根柱子不可能接到雨水
let left_max = 0, right_max = 0;
for (let j = i; j >= 0; --j) { // 搜索左边的最大值(包括自己:防止最后得到的最大值小于 height[i],最后计算 ans 时加了一个负数)
left_max = Math.max(left_max, height[j]);
}
for (let j = i; j < n; ++j) { // 搜索右边的最大值(包括自己)
right_max = Math.max(right_max, height[j]);
}
ans += (Math.min(left_max, right_max) - height[i]);
}
return ans;
};
解题二:动态规划
在暴力方法中,我们仅仅为了找到最大值每次都要向左和向右扫描一次。但是我们可以提前存储这个值,用空间去换时间。
// javascript
var trap = function(height) {
const n = height.length;
const left_max = new Array(n), right_max = new Array(n);
left_max[0] = height[0];
for (let i = 1; i < n; ++i) { // 搜索左边的最大值(包括自己:防止最后得到的最大值小于 height[i],最后计算 ans 时加了一个负数)
left_max[i] = Math.max(left_max[i - 1], height[i]);
}
right_max[n - 1] = height[n - 1];
for (let i = n - 2; i >= 0; --i) { // 搜索右边的最大值(包括自己)
right_max[i] = Math.max(right_max[i + 1], height[i]);
}
let ans = 0;
for (let i = 1; i < n - 1; ++i) { // 第一和最后一根柱子不可能接到雨水
ans += (Math.min(left_max[i], right_max[i]) - height[i]);
}
return ans;
};
解题三:单调栈
详细思路参考:【接雨水】单调递减栈,简洁代码,动图模拟
// javascript
var trap = function(height) {
const n = height.length;
const stack = new Array();
let ans = 0, i = 0;
while (i < n) {
while (!isEmpty(stack) && height[i] > height[peek(stack)]) {
const cur = stack.pop();
if (isEmpty(stack)) break; // height[last] 前面没有界定的条形
const left = peek(stack), right = i;
const distance = right - left - 1;
const bounded_height = Math.min(height[right], height[left]) - height[cur];
ans += distance * bounded_height;
}
stack.push(i);
++i;
}
return ans;
};
const isEmpty = (stack) => {
return stack.length === 0;
};
const peek = (stack) => {
return stack[stack.length - 1];
};
解题四:双指针
// javascript
var trap = function(height) {
let left = 0, right = height.length - 1;
let ans = 0;
let left_max = 0, right_max = 0;
while (left < right) {
if (height[left] < height[right]) {
if (height[left] > left_max) {
left_max = height[left];
} else {
ans += (left_max - height[left]);
}
++left;
}
else {
if (height[right] > right_max) {
right_max = height[right];
} else {
ans += (right_max - height[right]);
}
--right;
}
}
return ans;
};
另一种写法参考:接雨水
// javascript
var trap = function(height) {
let ans = 0;
let left = 0, right = height.length - 1;
let leftMax = 0, rightMax = 0;
while (left < right) {
leftMax = Math.max(leftMax, height[left]);
rightMax = Math.max(rightMax, height[right]);
// if (height[left] < height[right]) {
if (leftMax < rightMax) {
ans += (leftMax - height[left]);
++left;
} else {
ans += (rightMax - height[right]);
--right;
}
}
return ans;
};