@@ -89,22 +89,31 @@ public int trap(int[] height) {
89
89
90
90
91
91
/*
92
- 双指针
92
+ 双指针:
93
+ 1、变量含义
94
+ leftMax:左边的最大值,它是从左往右遍历找到的
95
+ rightMax:右边的最大值,它是从右往左遍历找到的
96
+ left:从左往右处理的当前下标
97
+ right:从右往左处理的当前下标
98
+ 2、双指针left、right的作用是 从两端向中间遍历整个数组,记录左右最大值,并计算每个位置的雨水
99
+ 3、在某个位置i处,它能存的水,取决于它左右两边的最大值中较小的一个,与当前位置的高度差
100
+ 4、在某个位置i处,它左边最大值一定是leftMax,右边最大值大于等于rightMax
101
+ 所以如果 leftMax <= rightMax,那么 左边最大值 <= 右边最大值,那么位置i的 左右最大值 较小者就是 leftMax
102
+ 所以当 leftMax <= rightMax 时,就去处理left下标,反之就去处理right下标
93
103
*/
94
104
class Solution {
95
105
public int trap (int [] height ) {
96
- int n = height .length ;
97
- int sum = 0 ;
106
+ int left = 0 , right = height .length - 1 ;
98
107
int leftMax = 0 , rightMax = 0 ;
99
- int left = 1 , right = n - 2 ;
100
- for ( int i = 1 ; i < n - 1 ; i ++ ) {
101
- if (height [ left - 1 ] < height [ right + 1 ] ) {
102
- leftMax = Math .max (leftMax , height [ left - 1 ]);
103
- sum += (leftMax > height [left ]) ? leftMax - height [ left ] : 0 ;
108
+ int sum = 0 ;
109
+ while ( left <= right ) {
110
+ if (leftMax <= rightMax ) {
111
+ sum + = Math .max (0 , leftMax - height [ left ]);
112
+ leftMax = Math . max (leftMax , height [left ]);
104
113
left ++;
105
114
} else {
106
- rightMax = Math .max (rightMax , height [right + 1 ]);
107
- sum += (rightMax > height [right ]) ? rightMax - height [ right ] : 0 ;
115
+ sum + = Math .max (0 , rightMax - height [right ]);
116
+ rightMax = Math . max (rightMax , height [right ]);
108
117
right --;
109
118
}
110
119
}
@@ -114,26 +123,32 @@ public int trap(int[] height) {
114
123
115
124
116
125
/*
117
- 栈
126
+ 单调递减栈:
127
+ 1、单调递减栈,height元素作为右柱依次入栈,出现入栈元素(右柱)比栈顶大时,说明在右柱左侧形成了低洼处
128
+ 2、栈不为空,且当前元素(右柱)比栈顶(右柱的左侧)大,说明形成低洼处了
129
+ 3、低洼处出栈后,栈如果为空,说明没有左柱,不能接雨水
130
+ 4、否则,获取低洼处、左柱、右柱的高度,计算雨水。
131
+ 积攒的水 = 距离 * 高度差
132
+ = (右柱位置-左柱位置-1) * (min(右柱高度, 左柱高度)-低洼处高度)
133
+ 5、循环结算完雨水后,右柱入栈,保证了栈内元素单调递减
118
134
*/
119
135
class Solution {
120
136
public int trap (int [] height ) {
121
137
int sum = 0 ;
122
- int index = 0 ;
123
138
Stack <Integer > stack = new Stack <>();
124
- while (index < height .length ) {
125
- while (!stack .empty () && height [index ] > height [stack .peek ()]) {
126
- int outVal = height [stack .peek ()];
127
- stack .pop ();
139
+ for (int right = 0 ; right < height .length ; right ++) {
140
+ while (!stack .empty () && height [right ] > height [stack .peek ()]) {
141
+ int bottom = stack .pop ();
128
142
if (stack .empty ()) {
129
143
break ;
130
144
}
131
- int distance = index - stack .peek () - 1 ;
132
- int minVal = Math .min (height [stack .peek ()], height [index ]);
133
- sum += distance * (minVal - outVal );
145
+ int left = stack .peek ();
146
+ int bottomHeight = height [bottom ];
147
+ int leftHeight = height [left ];
148
+ int rightHeight = height [right ];
149
+ sum += (right - left - 1 ) * (Math .min (leftHeight , rightHeight ) - bottomHeight );
134
150
}
135
- stack .push (index );
136
- index ++;
151
+ stack .push (right );
137
152
}
138
153
return sum ;
139
154
}
0 commit comments