目录
- 题目
- 1- 思路
- 2- 实现
- ⭐42. 接雨水——题解思路
- 3- ACM实现
题目
- 原题连接:42. 接雨水
1- 思路
模式识别:求雨水的面积 ——> 不仅是只求一个比当前元素大的元素,还要求面积
单调栈
- 应用场景,需要找到左边比当前元素大的元素
单调栈实现
- 当前元素和栈口元素作比较,如果当前元素大于栈口元素,此时收集结果:
- 例如 栈口元素是 10,如果当前元素是 30
- 此时找到 元素 10 右侧第一个比 它大的元素值是 30
- 右侧第一个比他大的元素是 栈里的第二个元素
单调栈的维护
- 单调栈与当前元素,存在三种情况,① 等于、②小于、③大于。要用单调栈来存储遍历过的元素
- 如果小于等于 栈口元素,此时直接入栈
- 如果大于栈口元素,此时收集结果
- ①凹槽底部元素:
int mid = st.top();
st.pop();
- ②计算水高:
int h = Math.min(st.top(),height[i])-height[mid];
从右侧柱高,和左侧柱高取个最小值 - ③计算雨水面积宽度:
int width = i - st.pop() - 1;
- ④计算面积:
area = h * width;
- ①凹槽底部元素:
2- 实现
⭐42. 接雨水——题解思路
class Solution {
public int trap(int[] height) {
int sum = 0;
if(height.length == 0){
return 0;
}
// 定义栈
Stack<Integer> st = new Stack<Integer>();
st.push(0);
for(int i = 1 ; i < height.length;i++){
if(height[i] <= height[st.peek()]){
st.push(i);
}else{
while(!st.isEmpty() && height[i] > height[st.peek()]){
int mid = st.peek();
st.pop();
if(!st.isEmpty()){
int h = Math.min(height[st.peek()],height[i]) - height[mid];
int width = i-st.peek() - 1;
int hold = h*width;
sum+=hold;
}
}
st.push(i);
}
}
return sum;
}
}
3- ACM实现
public class getRain {
public static int getRain(int[] nums){
// 定义单调栈
int len = nums.length;
if(len==0){
return 0;
}
int sum = 0;
Stack<Integer> st = new Stack<>();
st.push(0);
for(int i = 1 ; i < len;i++){
if(nums[i]<=nums[st.peek()]){
st.push(i);
}else{
while(!st.isEmpty() && nums[i] > nums[st.peek()]){
int mid = st.peek();
st.pop();
if(!st.isEmpty()){
int h = Math.min(nums[st.peek()],nums[i])-nums[mid];
int width = i - st.peek()-1;
int hold = h*width;
sum+=hold;
}
}
}
st.push(i);
}
return sum;
}
public static void main(String[] args) {
// 计算
Scanner sc = new Scanner(System.in);
System.out.println("输入数组长度");
int n = sc.nextInt();
int[] nums = new int[n];
for(int i = 0 ; i < n ; i ++){
nums[i] = sc.nextInt();
}
System.out.println("雨水面积是"+getRain(nums));
}
}