用自定义链式栈解决力扣括号匹配问题
时间:2022-07-23
本文章向大家介绍用自定义链式栈解决力扣括号匹配问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
一、背景
在力扣题库中有一道经典的栈表应用问题:有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 有效字符串需满足: 1、 左括号必须用相同类型的右括号闭合。 2、左括号必须以正确的顺序闭合。 3、注意空字符串可被认为是有效字符串。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/valid-parentheses
示例1 |
示例 2 |
示例 3 |
示例 4 |
示例 5 |
---|---|---|---|---|
输入: "()" |
输入: "()[]{}" |
输入: "(]" |
输入: "([)]" |
输入: "{[]}" |
输出: true |
输出: true |
输出: false |
输出: false |
输出: true |
二、解题思路
- 栈先入后出特点恰好与本题括号排序特点一致,即若遇到左括号入栈,遇到右括号时将对应栈顶左括号出栈,遍历完所有括号后 stack仍然为空,则认为字符串中的括号都完全匹配;
- 如果输入的字符串中有括号外的其它字符,则直接返回无效;
- 如果输入了空字符串,则不会产生入栈,栈仍然为空,也可返回有效。
三、编码实现
由于输入的字符串长度不定,并考虑自定义一个链式栈(无栈满问题,空间可扩充)进行编码实现。
1、结点
每个元素,除了存储其本身的信息(数据域)之外,还需存储一个指示其直接后继存放位置的指针。这两部分信息组成数据元素的存储映像,称为结点(Node)。
/**
* 结点类
*
* @author zhuhuix
* @date 2020-05-29
*/
public class Node<T> {
// 数据域
private T data;
// 指针
private Node<T> next;
Node(T t, Node<T> n) {
this.data = t;
this.next = n;
}
public T getData() {
return data;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
}
2、链式栈
- 链式栈是由N个结点组成的;
- 入栈出栈都在栈顶完成;
- 从栈顶以下的结点的指针链接下一个结点,直至栈尾。
/**
* 链栈的实现
*
* @author zhuhuix
* @date 2020-05-29
*/
public class LinkStack<T> {
// 栈顶元素
private Node<T> top;
// 栈的长度
private Integer length;
// 构造方法
public LinkStack() {
this.top = null;
this.length = 0;
}
// 入栈push
public void push(T t) {
this.top = new Node<>(t, this.top);
this.length++;
}
// 出栈pop
public T pop() {
if (this.top == null) {
return null;
}
T data = this.top.getData();
this.top = this.top.getNext();
this.length--;
return data;
}
// 查看栈顶元素
public T peek() {
if (this.top == null) {
return null;
}
T data = this.top.getData();
return data;
}
// 栈是否为空
public boolean isEmpty(){
return this.length==0;
}
// 销毁栈
public void destroy() {
this.top =null;
this.length = 0;
}
public Integer getLength() {
return this.length;
}
}
3、用链式栈实现括号匹配的判断
/**
* ==用链式栈解决力扣括号匹配问题==
* <p>
* 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
* 有效字符串需满足:
* 左括号必须用相同类型的右括号闭合。
* 左括号必须以正确的顺序闭合。
* 注意空字符串可被认为是有效字符串。
* <p>
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/valid-parentheses
*
* @author zhuhuix
* @date 2020-05-30
*/
public class LinkStackTest {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入只包括 '(',')','{','}','[',']' 的字符串");
String s = bufferedReader.readLine();
if (isValid(s)) {
System.out.println("字符串的括号相互匹配,有效");
} else {
System.out.println("字符串的括号不匹配,无效");
}
}
/**
* 通过左括号入栈,右括号出栈的算法判断括号是否匹配
*
* @param s 待判断的字符串
* @return 不匹配返回false, 匹配返回true
*/
public static boolean isValid(String s) {
LinkStack<String> stack = new LinkStack<>();
for (int i = 0; i < s.length(); i++) {
String ch = s.substring(i, i + 1);
switch (ch) {
// 左括号入栈
case "(":
case "[":
case "{":
stack.push(ch);
break;
case ")":
if (stack.isEmpty()) {
return false;
}
// 如果栈顶为左小括号,则匹配出栈
if ("(".equals(stack.peek())) {
stack.pop();
} else {
return false;
}
break;
case "]":
if (stack.isEmpty()) {
return false;
}
// 如果栈顶为左中括号,则匹配出栈
if ("[".equals(stack.peek())) {
stack.pop();
} else {
return false;
}
break;
case "}":
if (stack.isEmpty()) {
return false;
}
// 如果栈顶为左大括号,则匹配出栈
if ("{".equals(stack.peek())) {
stack.pop();
} else {
return false;
}
break;
default:
return false;
}
}
return stack.isEmpty();
}
}
四、代码执行
测试1
测试2
测试3
空字符串测试
- 【Go 语言社区】使用 Redis 实现排行榜功能
- 使用12c PDB整合环境的总结 (r10笔记第66天)
- 【Go 语言社区】Redis(ZADD)简单排名
- C得到文件的大小
- 【Go 语言社区】Go语言实现选择法排序实例
- 【Go 语言社区】Go语言转换所有字符串为大写或者小写的方法
- Go语言按字节截取字符串的方法
- Go语言中字符串的查找方法小结
- 优化算法——遗传算法
- 每秒执行6000的简单SQL优化(一)(r10笔记第62天)
- 【Go 语言社区】在golang里实现类似try catch 的异常处理机制
- 每秒执行6000的简单SQL优化(二) (r10笔记第65天)
- 【Go 语言社区】GO语言练习:网络编程 ICMP 示例
- Golang的json操作
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 别人变强靠天赋,而我,靠思维导图
- Spring Boot 五种热部署方式
- 二叉树最小深度
- 一日一技:限定Python函数只能被特定函数调用
- 四种ABAP单元测试隔离(test isolation)技术
- Python使用对象方式获取字典的值
- Hive整合HBase实现数据同步
- [数据结构与算法] 盘点工作中常用的算法
- MyBatis_resultMap 的关联方式实现多表查询(多对一)
- MyBatis_resultMap的N+1方式实现多表查询(多对 一)
- LeetCode 63. 不同路径 II
- 那些年遇到的刁钻JavaScript面试题(可防踩坑)
- JWT登录鉴权操作笔记 原
- c/c++补完计划(二-改): c字符串复制
- 来个鹅厂C语言面试题试试手?