链接: 503. 下一个更大元素 II
链接: 42. 接雨水
503. 下一个更大元素 II
关于循环数组的解题方法:
- 直接扩充数组至两倍大小
example: [1, 2, 1] -> [1, 2, 1, 1, 2, 1] - 下标取模避免数组越界:i % nums.length
class Solution {
public int[] nextGreaterElements(int[] nums) {
//边界判断
if(nums == null || nums.length <= 1) {
return new int[]{-1};
}
int[] res = new int[nums.length];
Stack<Integer> stack = new Stack<>();
stack.push(0);
Arrays.fill(res,-1);
for(int i = 1; i < nums.length*2; i++){
while(!stack.isEmpty() && nums[i % nums.length] > nums[stack.peek()]){
res[stack.peek()] = nums[i % nums.length];
stack.pop();
}
stack.push(i % nums.length);
}
return res;
}
}
42. 接雨水 (这道题很抽象)
class Solution {
public int trap(int[] height) {
/**
单调栈是按照 行 的方向来计算雨水
从栈顶到栈底的顺序:从小到大
通过三个元素来接水:栈顶,栈顶的下一个元素,以及即将入栈的元素
雨水高度是 min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度
雨水的宽度是 凹槽右边的下标 - 凹槽左边的下标 - 1(因为只求中间宽度)
*/
if(height.length <= 2) return 0;
int sum = 0; // 用来存放凹槽的面积
Stack<Integer> stack = new Stack<>();
stack.push(0);
for(int i = 1; i < height.length; i++){
if(height[i] < height[stack.peek()]){ // 情况一
stack.push(i);
}else if(height[i] == height[stack.peek()]){ // 情况二
// 因为相等的相邻墙,左边一个是不可能存放雨水的,所以pop左边的index, push当前的index
stack.pop();
stack.push(i);
}else{ // 情况三
while(!stack.isEmpty() && height[i] > height[stack.peek()]){
int mid = stack.pop();
if(!stack.isEmpty()){
int left = stack.peek(); // 左边柱子的高度
int h = Math.min(height[i],height[left]) - height[mid]; // 计算高度
int w = i - left - 1;
sum += h*w;
}
}
}
stack.push(i);
}
return sum;
}
}