503.下一个更大元素II
本题跟题目739类似,唯一不同的是要记录的是下一个更大元素了,而不是下标,而且添加了循环数组
本题将单调栈与循环数组结合起来,可以把数组看成是原来的两倍相当于模拟循环
代码实现
class Solution {
public int[] nextGreaterElements(int[] nums) {
int[] res=new int[nums.length];
Deque<Integer> stack=new LinkedList<>();
int m=nums.length;
Arrays.fill(res,-1);
stack.push(0);
//记住单调栈存放的是元素的下标
for(int i=1;i<2*m;i++){
if(nums[i%m]<=nums[stack.peek()]){//当前遍历的元素小于等于栈顶元素,直接把下标入栈
stack.push(i%m);
}
else{
while(!stack.isEmpty()&&nums[i%m]>nums[stack.peek()]){
res[stack.peek()]=nums[i%m];
stack.pop();
}
stack.push(i%m);
}
}
return res;
}
}
42.接雨水(大厂面试经典)
双指针解法,
求出每一列可以接收多少雨水,第一列和最后一列无法接收雨水,
class Solution {
public int trap(int[] height) {
int n=height.length;
int rain=0;
for(int i=0;i<n;i++){
if(i==0||i==n-1){continue;}
int lheight=height[i];
int rheight=height[i];
for(int j=i-1;j>=0;j--){
//求该列左边最高
if(height[j]>lheight){lheight=height[j];}
}
for(int j=i+1;j<n;j++){
if(height[j]>rheight){rheight=height[j];}//小细节这里要height[j]>rheight而不是height[j]height[i]
}
int h=Math.min(lheight,rheight)-height[i];
// System.out.println(h);
if(h>0){//小细节,h>0
rain+=h;
}
}
return rain;
}
}
//单调栈解法
单调栈解法
单调栈从栈头到栈底应该是从小到大的顺序(我们在栈头弹出元素),因为我们要接雨水需要形成一个凹槽,分为三种情况考虑:
1.如果当前元素小于栈头元素,那么直接push当前元素;
2.如果当前元素等于栈头元素,那么我们先pop栈头元素再push当前元素;
3.如果当前元素大于栈头元素,我们先计算能接到的雨水体积再push当前元素
代码实现
class Solution {
public int trap(int[] height) {
Stack<Integer> stack=new Stack<>();
if(height.length<=2){return 0;}
stack.push(0);
int result=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()]){//注意这里的height[stack.peek()]不要只写stack.peek()
stack.pop();
stack.push(i);
}
else{
while (!stack.isEmpty()&&(height[i]>height[stack.peek()])){
int mid=stack.pop();
if(!stack.isEmpty()){//不加这个条件判断会出现java.util.EmptyStackException
int left=stack.peek();//这里是peek而不是pop
int myHeight=Math.min(height[i],height[left])-height[mid];
int width=i-left-1;
int sum=myHeight*width;
if(sum>0){
result+=sum;//计算的是从left-i这个范围的接水体积
}
}
}
stack.push(i);
}
}
return result;
}
}