代码随想录训练营第59天|503.下一个更大元素Ⅱ、42.接雨水

503.下一个更大元素Ⅱ、42.接雨水

503.下一个更大元素Ⅱ

类似于下一个更大元素Ⅰ,对于下一个更大元素Ⅱ,我们可以利用相同的处理方法,即用单调栈的思想,但是要访问的数组是可以循环的,因此,我们访问两遍数组即可。

具体来说,我们可以使用一个栈来维护一个单调递减的序列,栈中存储的是 nums2 数组中的下标。当遍历到一个新的元素时,我们将栈顶元素与当前元素比较,如果栈顶元素小于当前元素,那么栈顶元素的下一个更大元素就是当前元素。我们可以将栈顶元素出栈,并将其下一个更大元素存储到哈希表中。重复这个过程,直到栈为空或者栈顶元素大于等于当前元素。最后,将当前元素的下标入栈。

最后,我们可以遍历 nums1 数组,从哈希表中查找每个元素的下一个更大元素。如果哈希表中存在该元素的下一个更大元素,就将其存储到结果数组中。否则,将 -1 存储到结果数组中。

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
    vector<int>result(nums.size(),-1);
    stack<int>st;
    for(int ii =0;ii<2*nums.size();ii++)
    {
        while(!st.empty()&&nums[st.top()]<nums[ii%nums.size()])
        {
           result[st.top()] = nums[ii%nums.size()];
           st.pop();
        }
        st.push(ii%nums.size());
    }
    return result;
    }
};

42.接雨水

直接解法

可以发现,接雨水的数量取决于两个因素:左边最高的柱子和右边最高的柱子中较矮的那个,以及当前柱子的高度。因此,我们可以遍历一遍数组,分别记录每个位置左边最高的柱子和右边最高的柱子,然后再遍历一遍数组,计算每个位置能接到的雨水的数量。

具体来说,我们可以使用两个数组 left_max 和 right_max 来记录每个位置左边和右边最高的柱子高度。对于每个位置 i,它能接到的雨水的数量就是 min(left_max[i], right_max[i]) - height[i],如果这个值为负数,则说明当前位置不能接到雨水,因此将其置为 0。最后,将所有位置能接到的雨水的数量相加即可得到最终的答案。

代码

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if (n == 0) return 0;

        vector<int> left_max(n), right_max(n);
        left_max[0] = height[0];
        right_max[n - 1] = height[n - 1];

        for (int i = 1; i < n; i++) {
            left_max[i] = max(left_max[i - 1], height[i]);
        }

        for (int i = n - 2; i >= 0; i--) {
            right_max[i] = max(right_max[i + 1], height[i]);
        }

        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans += max(min(left_max[i], right_max[i]) - height[i], 0);
        }

        return ans;
    }
};

单调栈

我们可以维护一个单调递减的栈,用来存储高度递减的柱子的下标。当遍历到一个新的柱子时,如果当前栈为空,则将该柱子的下标入栈;否则,如果当前柱子的高度小于等于栈顶柱子的高度,则将该柱子的下标入栈;否则,我们可以弹出栈顶元素,计算当前位置能接到的雨水的数量,并将结果累加到答案中,直到当前栈为空或者栈顶柱子的高度大于当前柱子的高度。最后,将当前柱子的下标入栈。

代码

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int>st;
        int result = 0;
        st.push(0);
        for(int ii =1;ii<height.size();ii++)
        {
            while(!st.empty()&&height[ii]>height[st.top()])
            {
                if(st.size()==1)
                    st.pop();
                else
                {
                    int mid = st.top();
                    st.pop();
                    int front = st.top();
                    result+=(min(height[front],height[ii])-height[mid])*(ii-front-1);
                }
            }
            st.push(ii);
        }
        return result;
    }
};

你可能感兴趣的:(leetcode,算法,数据结构)