LeetCode栈的基础操作系列问题详细总结

LeetCode中考察栈的基础操作的问题有20. Valid Parentheses,71. Simplify Path,150. Evaluate Reverse Polish Notation等,本文对这三个题进行详细的解析。

栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作是一种先进后出(LIFO)的数据结构。其最基础的操作包括创建一个栈(Stack())、入栈(push(E item))和出栈(pop())。下面是相关的Java API。
创建栈
push()
pop()
接下来使用这些基础操作来解决实际问题:

LeetCode 20. Valid Parentheses

Description:

Given a string containing just the characters ‘(’, ‘)’, ‘{’, ‘}’, ‘[’ and ‘]’, determine if the input string is valid.

An input string is valid if:

  1. Open brackets must be closed by the same type of brackets.
  2. Open brackets must be closed in the correct order.

Note that an empty string is also considered valid.

Example 1:

Input: "()"
Output: true

Example 2:

Input: "()[]{}"
Output: true

Example 3:

Input: "(]"
Output: false

Example 4:

Input: "([)]"
Output: false

Example 5:

Input: "{[]}"
Output: true

思路解析:

题意是给定一个包含括号的字符串,判断是否可以匹配。

本题考查栈的基础应用,可以利用栈的入栈、出栈操作完成解答。

对字符串的每个字符进行遍历,如果是左括号,进行入栈操作;

这一步完成需要判断一下栈是否为空,也就是说如果刚开始的是右括号的话,明显是不可匹配的,直接返回false;

上面已经判断了不是左括号,接着就要判断右括号和栈顶的括号(执行pop()操作)是否匹配,不匹配直接返回false;

最后注意遍历完成以后,如果全部匹配的话,push()和pop()操作是成对出现的,返回的是stack.isEmpty(),这样也可以保证了题目中“Note that an empty string is also considered valid”,空串也认为是可以匹配的。

代码如下:

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for(int i = 0 ; i < s.length() ; i ++){
            char c = s.charAt(i);
            if(c == '(' || c == '[' || c == '{'){
                stack.push(c);
            } else{
                if(stack.isEmpty()){
                    return false;
                }
                char topChar = stack.pop();
                if(c == ')' && topChar != '(')
                    return false;
                if(c == ']' && topChar != '[')
                    return false;
                if(c == '}' && topChar != '{')
                    return false;
            }
        }
        return stack.isEmpty();
    }
}

LeetCode 71. Simplify Path

Description:

Given an absolute path for a file (Unix-style), simplify it.

For example,
path = “/home/”, => “/home”
path = “/a/./b/…/…/c/”, => “/c”
path = “/a/…/…/b/…/c//.//”, => “/c”
path = “/a//bc/d//././/…”, => “/a/b/c”

In a UNIX-style file system, a period (’.’) refers to the current directory, so it can be ignored in a simplified path. Additionally, a double period ("…") moves up a directory, so it cancels out whatever the last directory was. For more information, look here: https://en.wikipedia.org/wiki/Path_(computing)#Unix_style

Corner Cases:

  • Did you consider the case where path = “/…/”?
    In this case, you should return “/”.
  • Another corner case is the path might contain multiple slashes ‘/’
    together, such as “/home//foo/”. In this case, you should ignore
    redundant slashes and return “/home/foo”.

思路解析:

本题题意是简化路径,考查栈的基础操作。

具体操作是把路径看做是由一个或多个"/“分割开的多个子字符串,把它们分别提取出来进行处理。如果是”.“的情况直接去掉,是”…“时删掉它上面挨着的一个路径;如果是空的话返回”/",如果有多个"/"只保留一个。

对应于栈,如果是"…",出栈;如果不是".“或者”…",也不为空,入栈。

代码如下:

class Solution {
    public String simplifyPath(String path) {
        Stack<String> stack = new Stack<>();
        String[] p = path.split("/");
        for (String t : p) {
            if (!stack.isEmpty() && t.equals("..")) {
                stack.pop();
            } else if (!t.equals(".") && !t.equals("") && !t.equals("..")) {
                stack.push(t);
            }
        }
        List<String> list = new ArrayList(stack);
        return "/" + String.join("/", list);
    }
}

LeetCode 150. Evaluate Reverse Polish Notation

Description:

Evaluate the value of an arithmetic expression in Reverse Polish Notation.

Valid operators are +, -, *, /. Each operand may be an integer or another expression.

Note:

  • Division between two integers should truncate toward zero.
  • The given RPN expression is always valid. That means the expression
    would always evaluate to a result and there won’t be any divide by
    zero operation.

Example 1:

Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9

Example 2:

Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6

Example 3:

Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
Output: 22
Explanation: 
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

思路解析:

本题是要计算逆波兰表达式的值,主要考查栈的基础应用,入栈和出栈操作。

具体做法:从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,进行运算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,得出的值即为表达式的结果。

更多关于逆波兰表达式可以参考https://blog.csdn.net/u014116780/article/details/82964481

代码如下:

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<Integer>();
        for(int i=0;i<tokens.length;i++){
            if(isInteger(tokens[i])){
                stack.push(Integer.parseInt(tokens[i]));
            }else{
                int num1 = stack.pop();
                int num2 = stack.pop();
                int res = operate(tokens[i],num1,num2);
                stack.push(res);
            }
        }
        return stack.pop();
    }
    
    public boolean isInteger(String string){
        try{
            if(Integer.parseInt(string)>=Integer.MIN_VALUE && Integer.parseInt(string)<=Integer.MAX_VALUE){
                return true;
            }
        }catch(Exception e){
            return false;
        }
        return false;
    }
    
    public int operate(String operation, int num1, int num2){
        if("+".equals(operation)){
            return num1 + num2;
        }else if("*".equals(operation)){
            return num1 * num2;
        }else if("/".equals(operation)){
            return num2 / num1;
        }else if("-".equals(operation)){
            return num2 - num1;
        }else{
            throw new RuntimeException("operation error!");
        }
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

James Shangguan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值