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

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

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

Stack

public Stack()
Creates an empty Stack.

push

public E push(E item)
Pushes an item onto the top of this stack. This has exactly the same effect as:
addElement(item)
Parameters:item - the item to be pushed onto this stack.
Returns:the item argument.See Also:Vector.addElement(E)

pop

public E pop()
Removes the object at the top of this stack and returns that object as the value of this function.
Returns:The object at the top of this stack (the last item of the Vector object).
Throws:EmptyStackException - if this stack is empty.

接下来使用这些基础操作来解决实际问题:

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:

Open brackets must be closed by the same type of brackets.
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//b////c/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 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,得出的值即为表达式的结果。
更多关于逆波兰表达式可以参考前缀、中缀、后缀表达式(逆波兰表达式)

代码如下:

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!");
        }
    }
}
posted @   James_Shangguan  阅读(405)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示