LeetCode-堆栈的使用

 

20. Valid Parentheses 有效的配对

https://leetcode.com/problems/valid-parentheses/

题目:如果一个字符串只包含‘(’,‘)、’{‘、’}‘、’[‘和’]‘,则确定输入字符串是否有效。打开括号必须由相同类型的括号关闭,则输入字符串是有效的。开括号必须按照正确的顺序关闭。注意,空字符串也被认为是有效的。

思路:新建一个栈,遍历输入字符串,如果当前字符为左半边括号,则将其压入栈中;如果当前字符为右半边括号且栈为空,则直接返回false;如果当前字符为右半边括号且栈不为空,则取出栈顶元素,若为对应的左半边括号,则继续循环,反之返回false。

 

32. Longest Valid Parentheses 最长有效配对

https://leetcode.com/problems/longest-valid-parentheses/

题目:给定一个只包含字符‘(’和‘)’的字符串,查找最长的有效(格式良好)括号子字符串的长度。

思路:

①使用Stack栈

②DP动态规划

class Solution {
    public int longestValidParentheses(String s) {
        // using Stack
        Stack<Integer> st = new Stack<>();
        int result = 0;
        st.push(-1);
        for(int i = 0; i < s.length(); i++) {
            if(s.charAt(i) == ')' && st.size() > 1 && s.charAt(st.peek()) == '(') {
                st.pop();
                result = Math.max(result, i - st.peek());
            } else {
                st.push(i);
            }
        }
        return result;
    }
}
class Solution {
    public int longestValidParentheses(String s) {
        // using DP
        int[] dp = new int[s.length()];
        int result = 0, leftCount = 0;
        for(int i = 0; i < s.length(); i++) {
            if(s.charAt(i) == '(') {
                leftCount++;
            } else if(leftCount > 0) {
                dp[i] = dp[i - 1] + 2;
                dp[i] += (i - dp[i]) > 0 ? dp[i - dp[i]] : 0;
                result = Math.max(result, dp[i]);
                leftCount--;
            }
        }
        return result;
    }
}

单调栈:单调栈分为单调递增栈和单调递减栈,单调递增栈即栈内元素保持单调递增的栈,同理单调递减栈即栈内元素保持单调递减的栈。

范式:
单调递增栈

for(int i = 0; i < T.size(); i++){
  while(! stk.empty() && stk.top() > T[i]){
    ​stk.pop();
  }
  stk.push(A[i]);
}

单调递减栈

for(int i = T.size() - 1; i >= 0; i--){
  while(! stk.empty() && T[i] >= stk.top()){
    stk.pop();
  }         
  stk.push(i);
}

单调栈的作用:

可以以 O(1) 的时间复杂度得知某个位置左右两侧比他大(或小)的数的位置,当你需要高效率获取某个位置左右两侧比他大(或小)的数的位置的的时候就可以用到单调栈。

求解数组中元素右边第一个比它小的元素的下标,从前往后,构造单调递增栈;求解数组中元素左边第一个比它大的元素的下标,从后往前,构造单调递增栈。
求解数组中元素右边第一个比它大的元素的下标,从前往后,构造单调递减栈;求解数组中元素左边第一个比它小的元素的下标,从后往前,构造单调递减栈。

42. Trapping Rain Water 装雨水

https://leetcode.com/problems/trapping-rain-water/

题目:如果n个非负整数表示一个标高图,其中每个杆的宽度为1,则计算雨后它能装多少水。

思路:使用单调递减栈,存入递减的边界,当遍历到大于栈顶元素的数字时,就可能产生可以装水的地方。当可能产生能装水的地方时,我们先弹出栈顶,即当前最低点,然后再次弹出栈顶,即左边界,右边界为当前遍历到的数字;比较左右边界,取较小值为水的边界;然后此较小值减去最低点,乘以左右边界间的距离就是此处的装水量了。栈中存放的是坐标。

class Solution {
    public int trap(int[] height) {
        if(height.length < 2) return 0;
        Stack<Integer> stack = new Stack<Integer>();
        int res = 0, i = 0;
        while(i < height.length) {
            if(stack.empty() || height[i] < height[stack.peek()]) {
                stack.push(i++);
            } else {
                int t = stack.pop(); // 记录最小值
                if(stack.empty()) continue;
                // 边界中的较小值减去最小值 * 两个边界之间的距离
                res += (Math.min(height[i], height[stack.peek()]) - height[t])*(i - stack.peek() - 1);
            }
        }
        return res;
    }
}

84. Largest Rectangle in Histogram 直方图中的最大矩形

https://leetcode.com/problems/largest-rectangle-in-histogram/

题目:给定n个非负整数表示直方图的条高,其中每条的宽度为1,则在直方图中找出最大矩形的面积。

思路:使用递增栈,按从高板子到低板子的顺序处理,先处理最高的板子,然后再处理旁边矮一些的板子。当遇到大于栈顶元素的数字时进栈,当遇到小的数字时,取出栈顶元素进行处理。在计算矩形面积时,先取出栈顶元素,即最高的板子,然后就可以计算长度为1的矩形面积了,接着取下一块板子,此时按长度为2来计算矩形面积,以此类推,直到数字大于栈顶元素为止,再次进栈。为了使得最后一块板子也被处理,需要在高度数组最后面加上一个0,这样原先的最后一个板子也可以被处理了。

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        if(n == 1) return heights[0];
        int[] height = new int[n+1];
        for(int i = 0; i < n; i++) {
            height[i] = heights[i];
        }
        height[n] = 0;
        Stack<Integer> stack = new Stack<Integer>();
        int i = 0, res = 0;
        while(i < n+1) {
            if(stack.empty() || height[i] > height[stack.peek()]) {
                stack.push(i ++);
            }
            else {
                int t = stack.pop(); // 最高点
                res = Math.max(res, height[t] * (stack.empty() ? i : i - stack.peek() - 1));
            }
        }
        return res;
    }
}

149. Max Points on a Line 直线上最大的点

https://leetcode.com/problems/max-points-on-a-line/

题目:给定二维平面上的n个点,求出位于同一直线上最大的点。(暴力方法/细节实现)

思路:

 

150. Evaluate Reverse Polish Notation 求解逆波兰表示法的式子

https://leetcode.com/problems/evaluate-reverse-polish-notation/

题目:用反向波兰表示法计算算术表达式的值。有效运算符是+,-,*,/。每个操作数可以是一个整数,也可以是另一个表达式。注:两个整数之间的除数应截断为零。给定的RPN表达式始终有效。这意味着表达式将始终计算为一个结果,并且不会被零运算除以任何值。

思路:

 

转载于:https://www.cnblogs.com/nomad1c/p/11576980.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值