单调栈模型

单调栈本质: 及时去掉无用数据, 保证栈中数据有序。

单调栈的思考方法,假设我们要找寻右侧第一个大于当前数字的数,就要将<=当前数的元素出栈。

当拿到一个问题时,要大的,剔除小的;要小的,剔除大的。

 

模板题:

 

class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        n = len(temperatures)
        stk = []
        ans = [0] * n
        for i in range(n - 1, -1, -1):
            t = temperatures[i]
            while stk and t >= temperatures[stk[-1]]:
                stk.pop()
            if stk:
                ans[i] = stk[-1] - i
            stk.append(i)
        
        return ans

 

class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        n = len(temperatures)
        stk = []
        ans = [0] * n
        for i, t in enumerate(temperatures):
            while stk and temperatures[stk[-1]] < t:
                j = stk.pop()
                ans[j] = i - j
            stk.append(i)
        
        return ans

 

 

 数组的循环操作可以用模运算来实现

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        n = len(nums)
        stk = []
        ans = [-1] * n

        for i in range(n * 2):
            while stk and nums[stk[-1]] < nums[i % n]:
                j = stk.pop()
                ans[j] = nums[i % n]
            stk.append(i % n)
        
        return ans

 

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        n = len(nums)
        stk = []
        ans = [-1] * n

        for i in range(n * 2 - 1, -1, -1):
            while stk and nums[stk[-1]] <= nums[i % n]:
                stk.pop()
            if stk:
                ans[i % n] = nums[stk[-1]]
            stk.append(i % n)
        
        return ans

 

 

 

class Solution:
    def trap(self, height: List[int]) -> int:
        n = len(height)
        stk = []
        res = 0

        for i, val in enumerate(height):
            while stk and height[stk[-1]] <= val:
                bottom_h = height[stk.pop()]
                if not stk:
                    break
                left = stk[-1]
                dh = min(height[left], val) - bottom_h
                res += dh * (i - left - 1)
            stk.append(i)
        
        return res

 

 

 

class Solution {
public:
    int numberOfWeakCharacters(vector<vector<int>>& properties) {
        sort(properties.begin(), properties.end(), [&](auto &a, auto &b) {
            return a[0] == b[0] ? a[1] > b[1]: a[0] < b[0];
        });
        int n = properties.size();
        stack<int> stk;

        int res = 0;
        for(int i = 0; i < n; i ++ ) {
            while(stk.size() && properties[i][1] > properties[stk.top()][1]) {
                stk.pop();
                res ++ ;
            }
            stk.push(i);
        }

        return res;
    }
};

 

class Solution:
    def numberOfWeakCharacters(self, properties: List[List[int]]) -> int:
        n = len(properties)
        stk = []
        res = 0

        def cmp(a: tuple):
            return a[0], -a[1]

        properties.sort(key=cmp)

        for i in range(n):
            while stk and properties[stk[-1]][1] < properties[i][1]:
                stk.pop()
                res += 1
            stk.append(i)
        
        return res

 

双单调栈

 我们的单调栈每次回向外部弹出一个一个元素,在本题中,我们要用到这些被弹出的元素。

这些被弹出的元素有一个性质,就是他们的某一侧的最近的最值已经被找到了,那么这个题要找第二个比它大的,我们就在用一个单调栈将第一个单调栈弹出的数据弹出来,那么这个单调栈就可以统计右边第二大的数据了。

class Solution:
    def secondGreaterElement(self, nums: List[int]) -> List[int]:
        n = len(nums)
        s = []
        t = []
        ans = [-1] * n

        for i, x in enumerate(nums):
            while t and nums[t[-1]] < x:
                ans[t.pop()] = x
            j = len(s) - 1
            while j >= 0 and nums[s[j]] < x:
                j -= 1
            t += s[j + 1:]
            del s[j + 1:]
            s.append(i)

        return ans

 

posted @ 2023-11-18 10:32  深渊之巅  阅读(6)  评论(0编辑  收藏  举报