算法学习|单调栈 LeetCode 503.下一个更大元素II、42. 接雨水

一、下一个更大元素

给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

思路

思路一:重新定义一个数组,将两个nums数组拼接在一起,模拟成环的过程,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小。
思路二:首尾相连或者成环类的问题都可以用取模的方式模拟转圈的过程

实现代码

//思路一
class Solution {
    
    
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
    
    
        //拼接一个新的nums数组
        vector<int> nums1(nums.begin(), nums.end());
        nums.insert(nums.end(), nums1.begin(), nums1.end());
        //用新的nums大小来初始化result
        vector<int> result(nums.size(), -1);
        if(nums.size() == 0)  return result;
        stack<int> st;
        st.push(0);
        for(int i = 1; i < nums.size(); i++) {
    
    
            if (nums[i] < nums[st.top()]) st.push(i);
            else if (nums[i] == nums[st.top()]) st.push(i);
            else {
    
    
                while(!st.empty() && nums[i] > nums[st.top()]) {
    
    
                    result[st.top()] = nums[i];
                    st.pop();
                }
                st.push(i);
            }
        }
        result.resize(nums.size() / 2);
        return result;
    }
};
//思路二
class Solution {
    
    
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
    
    
        vector<int> result(nums.size(), -1);
        if(nums.size() == 0)  return result;
        stack<int> st;
        st.push(0);
        for(int i = 1; i < nums.size() * 2; i++) {
    
    
            if (nums[i % nums.size()] < nums[st.top()]) st.push(i % nums.size());
            else if (nums[i % nums.size()] == nums[st.top()]) st.push(i % nums.size());
            else {
    
    
                while(!st.empty() && nums[i % nums.size()] > nums[st.top()]) {
    
    
                    result[st.top()] = nums[i % nums.size()];
                    st.pop();
                }
                st.push(i % nums.size());
            }
        }
        return result;
    }
};

二、接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
在这里插入图片描述

思路

凹槽才可以接住雨水,所以寻找右边第一个比它高的柱子以及左边第一个比它高的柱子,而单调栈可以解决右边或左边第一个比它大或者小的数这类题目,所以本题也应该想到用单调栈。(横向求解)
1.如果当前遍历元素小于栈顶元素,直接入栈
2.如果当前遍历元素等于栈顶元素,直接入栈不影响计算结果(雨水面积为0),但是多计算了一次
3.如果当前遍历元素大于栈顶元素,那么就找到凹槽了(当前遍历元素就是右边第一个比它大的元素,栈顶元素右边的第一个元素就是左边第一个比它的元素),求雨水的宽度(当前遍历元素下标 - 栈顶元素的右边第一个元素下标)以及高度(左边元素和右边元素取最小值 - 中间柱子的高度)

实现代码

//暴力
class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
        int sum = 0;
        for(int i = 0; i < height.size(); i++) {
    
    
            if(i == 0 || i == height.size() - 1) continue;
            int rHeight = height[i];
            int lHeight = height[i];
            for(int r = i + 1; r < height.size(); r++) {
    
    
                if(height[r] > rHeight) rHeight = height[r]; 
            }
            for(int l = i - 1; l >= 0; l--) {
    
    
                if(height[l] > lHeight) lHeight = height[l];
            }
            int h = min(lHeight,rHeight) - height[i];
            if(h > 0) sum += h;
        }
        return sum;
    }
};
//单调栈
class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
        if (height.size() <= 2) return 0; // 可以不加
        stack<int> st; // 存着下标,计算的时候用下标对应的柱子高度
        st.push(0);
        int sum = 0;
        for (int i = 1; i < height.size(); i++) {
    
    
            if (height[i] < height[st.top()]) {
    
         
                st.push(i);
            } if (height[i] == height[st.top()]) {
    
     
                st.pop(); 
                st.push(i);
            } else {
    
                                   
                while (!st.empty() && height[i] > height[st.top()]) {
    
     
                    int mid = st.top();
                    st.pop();
                    if (!st.empty()) {
    
    
                        int h = min(height[st.top()], height[i]) - height[mid];
                        int w = i - st.top() - 1; // 注意减一,只求中间宽度
                        sum += h * w;
                    }
                }
                st.push(i);
            }
        }
        return sum;
    }
};

猜你喜欢

转载自blog.csdn.net/li26324949/article/details/130152304