503. 下一个更大的元素Ⅱ
题目描述
给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。
数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。
示例1:
输入:nums=[1,2,1]nums = [1,2,1]nums=[1,2,1]
输出:[2,−1,2][2,-1,2][2,−1,2]
示例1:
输入:nums=[1,2,3,4,3]nums = [1,2,3,4,3]nums=[1,2,3,4,3]
输出:[2,3,4,−1,4][2,3,4,-1,4][2,3,4,−1,4]
思路
在496题的基础上变成了循环数组,会想到,可以用两个nums拼接模拟。其他的部分和496完全相同。
解法
class Solution {
public int[] nextGreaterElements(int[] nums) {
if(nums == null || nums.length <= 1){
return new int[]{-1};
}
int size = nums.length;
int[] result = new int[size];
Arrays.fill(result,-1);
Stack<Integer> stk = new Stack<>();
for(int i = 0;i<2*size;i++){
while(!stk.isEmpty() && nums[i%size] > nums[stk.peek()]){
result[stk.peek()] = nums[i%size];
stk.pop();
}
stk.push(i % size);
}
return result;
}
}
总结
主要还是看单调栈的代码熟不熟悉,多多看,多多练。
42. 接雨水
题目描述
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例1:
输入:height=[0,1,0,2,1,0,1,3,2,1,2,1]height = [0,1,0,2,1,0,1,3,2,1,2,1]height=[0,1,0,2,1,0,1,3,2,1,2,1]
输出:666
示例2:
输入:height=[4,2,0,3,2,5]height = [4,2,0,3,2,5]height=[4,2,0,3,2,5]
输出:999
思路
本题可以有两种思路,一种是双指针,一种是单调栈。但我一种都没有,直接上答案了。
双指针:
记录左边柱子的最高高度和右边柱子的最高高度,就可以i计算当前位置的雨水面积,即,当前雨水面积=min(左边柱子的最高高度,右边柱子的最高高度)-当前柱子高度
为了能够得到两侧的最高高度,需要使用双指针来遍历,讲每个位置的左边最高高度记录在一个数组中,右边最高高度记录在另一个数组中,以避免重复计算。
单调栈:
其实会比双指针更好看出来一些,看到题的时候会有点单调栈的感觉。
本题在发现添加的柱子高度大于栈顶元素时,就出现了凹槽,也就可以加水了。故而需要单调栈内元素从小到大弹出。在遇到高度相同的柱子时,需要使用最右边的柱子来计算宽度。
解法1
class Solution {
public int trap(int[] height) {
int length = height.length;
if(length <= 2){
return 0;
}
int[] maxLeft = new int[length];
int[] maxRight = new int[length];
maxLeft[0] = height[0];
for(int i = 1;i<length;i++){
maxLeft[i] = Math.max(height[i],maxLeft[i-1]);
}
maxRight[length - 1] = height[length - 1];
for(int i = length - 2;i>=0;i--){
maxRight[i] = Math.max(height[i],maxRight[i+1]);
}
int sum = 0;
for(int i = 0;i<length;i++){
int count = Math.min(maxLeft[i],maxRight[i])-height[i];
if(count > 0){
sum += count;
}
}
return sum;
}
}
解法2
class Solution {
public int trap(int[] height) {
int size = height.length;
if(size <= 2){
return 0;
}
Stack<Integer> stk = new Stack<>();
stk.push(0);
int sum = 0;
for(int index = 1;index < size;index++){
int stkTop = stk.peek();
if(height[index] < height[stkTop]){
stk.push(index);
}
else if(height[index] == height[stkTop]){
stk.pop();
stk.push(index);
}
else{
int heightAtIndex = height[index];
while(!stk.isEmpty() && (heightAtIndex > height[stkTop])){
int mid = stk.pop();
if(!stk.isEmpty()){
int left = stk.peek();
int h = Math.min(height[left],height[index])-height[mid];
int w = index - left -1;
int hold = h*w;
if(hold > 0){
sum += hold;
}
stkTop = stk.peek();
}
}
stk.push(index);
}
}
return sum;
}
}
总结
好好看,好好学。