提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言

一、思路
写一半忘记这是双指针了
java
class Solution {
public int trap(int[] height) {
int max = height[0]; // 初始化为第一个元素
for (int i = 1; i < height.length; i++) {
if (height[i] > max) {
max = height[i];
}
}
int count=0;
for(int i=1;i<max;i++){
s1:for(int j=0;j<height.length;j++){
while(j==0 && height[j]<=0){//找到第一个边界 >i
continue s1;
}
if(j+1<height.length && height[j+1]<i){//找第一层空格
count++;
continue ;}
if(j==height.length-1 && height[j]==0){
return 0;
}
}
}
return count;
}
}
像俄罗斯方块一样,一层一层数,好在他这个盖不了顶。
二、加入双指针
按层计算,时间复杂度是O(N*柱子高度),虽然是没到O(N2),但是实际表现会更差。
java
class Solution {
public int trap(int[] height) {
int max = height[0]; // 初始化为第一个元素
for (int i = 1; i < height.length; i++) {
if (height[i] > max) {
max = height[i];
}
}
int count=0;
for(int i=1;i<=max;i++){
s1:for(int j=0;j<height.length;j++){
int right=j+1,tmp=0;
boolean flag=false;
while(height[j]<i){//找到第一个边界 >i
continue s1;
}
while(right<height.length){
if(height[right]<i){
tmp++;
right++;
}else{
flag=true;
count+=tmp;
tmp=0;
break;
}
}
// if(j+1<height.length && height[j+1]<i){//找第一层空格
// count++;
// continue ;}
if(j==height.length-1 && height[j]==0){
return 0;
}
}
}
return count;
}
}
三、在二的基础上优化--双指针
想法很简单,就是按层扫变成减法。从上往下条状减,不小心抄多了,反正是0ms

第二次看的时候有点纠结,不太理解左右哪边先减,后来想明白了,先从短的那边算起,保持顺序性。
java
class Solution {
public int trap(int[] height) {
// 1. 修复 Bug:处理空数组或长度不足 3 的情况(无法接水)
if (height == null || height.length < 3) {
return 0;
}
int left = 0;
int right = height.length - 1;
int leftMax = 0; // 记录左边遇到的最高柱子
int rightMax = 0; // 记录右边遇到的最高柱子
int count = 0; // 接水量
// 2. 双指针向中间逼近
while (left < right) {
// 核心逻辑:哪边的柱子矮,哪边就是"短板",水能接多少取决于短板
if (height[left] < height[right]) {
if (height[left] >= leftMax) {
leftMax = height[left]; // 遇到更高的柱子,更新最大值,不接水
} else {
count += leftMax - height[left]; // 当前柱子低于左边最大值,可以接水
}
left++; // 左指针向右移
} else {
// 处理右边(逻辑同上)
if (height[right] >= rightMax) {
rightMax = height[right];
} else {
count += rightMax - height[right];
}
right--; // 右指针向左移
}
}
return count;
}
}
四、Dp入门
先定义,再写基本式,再带入初值,最后让程序计算:
dp[n] 上n级台阶的解法
dp[n]=dp[n-1]+dp[n-2];
dp[1]=1,dp[2]=2

对于这题:

从左往右扫一次,从右往左扫一次,左右中小的那个减当前值

java
class Solution {
public int trap(int[] height) {
int n = height.length;
if (n <= 2) return 0;
// 1. 定义 DP 数组
int[] left_max = new int[n];
int[] right_max = new int[n];
// 2. 初始化 & 从左往右填表
left_max[0] = height[0];
for (int i = 1; i < n; i++) {
left_max[i] = Math.max(left_max[i - 1], height[i]);
}
// 3. 从右往左填表
right_max[n - 1] = height[n - 1];
for (int i = n - 2; i >= 0; i--) {
right_max[i] = Math.max(right_max[i + 1], height[i]);
}
// 4. 计算结果
int ans = 0;
for (int i = 0; i < n; i++) {
// 木桶效应:取两边最小的,减去自己的高度
ans += Math.min(left_max[i], right_max[i]) - height[i];
}
return ans;
}
}
五、单调栈入门
从下往上入栈,从上往下弹出;单调递增和递减都积不了水

这里想的是,递减,然后突然碰到高个,然后就可以积水,然后右边的板就是高个,左边的板是最大值,然后计算是从递减的最小值开始的,由于是递减的,所以栈顶是小值,也就是横着的最底一层(就象数格子一样,横着一排数完),慢慢变大就慢慢往上
总结
困难题就不追求那么多了,一不小心抄多了。
对我来说Dp和栈都比较有挑战性,栈比较怪,或许公司会问。