单调栈

55 阅读1分钟

leetcode.com/problems/su… 907. Sum of Subarray Minimums

Given an array of integers arr, find the sum of min(b), where b ranges over every (contiguous) subarray of arr. Since the answer may be large, return the answer modulo 10^9 + 7.

Example 1:

Input: arr = [3,1,2,4]
Output: 17
Explanation: 
Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4]. 
Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1.
Sum is 17.

Example 2:

Input: arr = [11,81,94,43,3]
Output: 444

 

Constraints:

  • 1 <= arr.length <= 3 * 104
  • 1 <= arr[i] <= 3 * 104

leetcode.cn/problems/re… 316. Remove Duplicate Letters

Given a string s, remove duplicate letters so that every letter appears once and only once. You must make sure your result is 

the smallest in lexicographical order

 among all possible results.

 

Example 1:

Input: s = "bcabc"
Output: "abc"

Example 2:

Input: s = "cbacdcbc"
Output: "acdb"

这道题用的方法是贪心 + 单调栈

本题最开始写出来了,但是写的一塌糊涂。整理一下代码.

  1. 确定map的含义,map的意思是遍历到index i,i后面还剩多少个数,比如说数组'bdabc',遍历到第一个b之后,后面还剩1个b。遍历到第二个b,后面还剩0个b。
  2. visited的含义是当前这个数还是否在栈里,如果在栈里就不添加到stack里了
  3. 栈里的元素就是最终的结果

做第二遍没做出来,值得反思

class Solution {
    public String removeDuplicateLetters(String s) {
        int[] map = new int[26]; // 后面还剩多少个数
        for(int i = 0; i < s.length(); i++) {
            map[s.charAt(i) - 'a']++;
        }

        boolean[] visited = new boolean[26]; // 当前这个数在不在栈里
        Arrays.fill(visited, false);
        Deque<Integer> stack = new LinkedList<>();
        for(int i = 0; i < s.length(); i++) {
            int curr = s.charAt(i) - 'a';
            if(!visited[curr]) {
                if(!stack.isEmpty() && curr > s.charAt(stack.peek()) - 'a') {
                    stack.push(i);
                    visited[curr] = true;
                } else {
                    while(!stack.isEmpty() && curr < s.charAt(stack.peek()) - 'a') {
                        if(map[s.charAt(stack.peek()) - 'a'] > 0){ // 后面还有
                            int index = stack.pop();
                            visited[s.charAt(index) - 'a'] = false;
                        } else {
                            break;
                        }
                    }
                    stack.push(i);
                    visited[curr] = true;
                }
            }
            map[curr]--;
        }
       
        StringBuilder res = new StringBuilder();
        while(!stack.isEmpty()) {
            res.append(s.charAt(stack.removeLast()));
        }
        return res.toString();
    }
}

42. Trapping Rain Water

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.

 

Example 1:

Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.

Example 2:

Input: height = [4,2,0,3,2,5]
Output: 9

Constraints:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

接雨水经典单调栈的题 具体看注释

class Solution {
    public int trap(int[] height) {
        int res = 0;
        Deque<Integer> stack = new ArrayDeque<>();
        for(int i = 0; i < height.length; i++) {
            if(!stack.isEmpty() && height[i] < height[stack.peek()]) {
                stack.push(i);
            } else {
                while(!stack.isEmpty() && height[i] > height[stack.peek()]) {
                    int mid = stack.poll(); // 这个是最低的柱子
                    if(!stack.isEmpty()) {
                        int h = Math.min(height[stack.peek()], height[i]) - height[mid];// 两边高柱子的最低值减去低柱子就是高度
                        int w = i - stack.peek() - 1; //宽度就是右边减左边
                        res += h * w; // 最后相乘就是面积
                    }
                }
                stack.push(i);
            }
        }

        return res;
    }
}