备战秋招60天算法挑战,Day13

题目链接: https://leetcode.cn/problems/valid-parentheses/

视频题解: https://www.bilibili.com/video/BV1hT421Q7g3/

LeetCode20.有效的括号

在我们刷题的时候,适当的借助现有的数据结构往往会起到事半功倍的效果,今天我们讨论一下栈的使用。栈的特点是先进后出,利用栈的这个特点可以巧妙的解决很多问题,借助下面这道题我们进一步来体会一下栈的妙用。

题目描述

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

举个例子:

复制代码
输入:s = "()"
输出:true

输入:s = "(]"
输出:false

视频题解

有效的括号

思路来源

思路来源

思路解析

首先要理解题意,什么才是题目中描述的有效括号,比如s = "({)[]}", 如下图,把同类型的括号单独按顺序拆出来,每种类型的括号都是能闭合的,但是s并不是合法的。

因为最先和'{'闭合的是')',违背了 左括号必须用相同类型的右括号闭合 这个原则。而且上面的这种拆法本身也违反了 左括号必须以正确的顺序闭合的原则

很多同学都因为没有理解透题意面试的时候没有把这道题正确的做出来,非常可惜。

理清题意,只需要借助栈,遍历字符串当元素为'(''{''['就压栈,遇到')''}'']'就和栈顶元素比较,能组成合法括号就弹出栈顶元素,不能组成合法括号就返回false,直到遍历完字符串,栈为空就返回true。整个匹配过程就像我们平时玩的小游戏消消乐。

举个简单的例子,s = "({}[])",匹配过程如下图:

遍历完s以后,栈是空的,这就说明字符串s是合法的。

C++代码

cpp 复制代码
class Solution {
public:
    //判断两个字符能否组成合法的括号
    bool isMatch(char& left, char& right) {
        if (left == '(' && right == ')') {
            return true;
        } else if (left == '{' && right == '}') {
            return true;
        } else if (left == '[' && right == ']') {
            return true;
        } else {
            return false;
        }
    }
    bool isValid(string s) {
        stack<char> st_ch;
        int s_len = s.length();
        //s的长度为奇数,一定是非法的
        if (s_len % 2 != 0) {
            return false;
        } 
        for (auto& ch:s) {
            //遇到'('、'{'、'['就压栈
            if (ch == '(' || ch == '{' || ch == '[')
                st_ch.push(ch);
            //遇到')'、'}'、']'就和栈顶元素比较,能组成合法括号就弹出栈顶元素
            //栈的操作一定要小心,不要对空栈进行pop操作
            else if (!st_ch.empty() && isMatch(st_ch.top(), ch))
                st_ch.pop();
            else 
                return false;
        }
        if (st_ch.empty()) {
            return true;
        } 
        return false;
    }
};

java代码

java 复制代码
class Solution {
    //判断两个字符能否组成合法的括号
    private boolean isMatch(char left, char right) {
        if (left == '(' && right == ')') {
            return true;
        } else if (left == '{' && right == '}') {
            return true;
        } else if (left == '[' && right == ']') {
            return true;
        } else {
            return false;
        }
    }
    
    public boolean isValid(String s) {
        Stack<Character> st_ch = new Stack<>();
        int s_len = s.length();
        //s的长度为奇数,一定是非法的
        if (s_len % 2 != 0) {
            return false;
        } 
        for (char ch : s.toCharArray()) {
            //遇到'('、'{'、'['就压栈
            if (ch == '(' || ch == '{' || ch == '[')
                st_ch.push(ch);
            //遇到')'、'}'、']'就和栈顶元素比较,能组成合法括号就弹出栈顶元素
            //栈的操作一定要小心,不要对空栈进行pop操作
            else if (!st_ch.empty() && isMatch(st_ch.peek(), ch))
                st_ch.pop();
            else 
                return false;
        }
        return st_ch.empty();
    }
}

python代码

python 复制代码
class Solution:
    def isValid(self, s: str) -> bool:
        st_ch = []
        s_len = len(s)
        #s的长度为奇数,一定是非法的
        if s_len % 2 != 0:
            return False
        for ch in s:
            #遇到'('、'{'、'['就压栈
            if ch == '(' or ch == '{' or ch == '[':
                st_ch.append(ch)
            #遇到')'、'}'、']'就和栈顶元素比较,能组成合法括号就弹出栈顶元素
            #栈的操作一定要小心,不要对空栈进行pop操作
            elif st_ch and self.isMatch(st_ch[-1], ch):
                st_ch.pop()
            else:
                return False
        return not st_ch
    
    #判断两个字符能否组成合法的括号
    def isMatch(self, left, right):
        if left == '(' and right == ')':
            return True
        elif left == '{' and right == '}':
            return True
        elif left == '[' and right == ']':
            return True
        else:
            return False

复杂度分析

时间复杂度: 只遍历一遍字符串,故时间复杂度是O(n)n为字符串长度。

空间复杂度: 我们用到了一个栈st_ch,故空间复杂度为O(n)n最大为字符串长度。

相关推荐
行百里er8 分钟前
优雅应对异常,从“try-catch堆砌”到“设计驱动”
java·后端·代码规范
天天鸭26 分钟前
前端仔写了个 AI Agent,才发现大模型只干了 10% 的活
前端·python·ai编程
ms_27_data_develop27 分钟前
Java枚举类、异常、常用类
java·开发语言
xiaohe0730 分钟前
Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)
java·数据库·spring boot
Irissgwe34 分钟前
进程间通信
linux·服务器·网络·c++·进程间通信
代码飞天35 分钟前
wireshark的高级使用
android·java·wireshark
Wave84535 分钟前
数据结构—树
数据结构
ic爱吃蓝莓41 分钟前
数据结构 | HashMap原理
数据结构·学习·算法·链表·哈希算法
add45a42 分钟前
C++编译期数据结构
开发语言·c++·算法
setmoon2141 小时前
使用Scikit-learn构建你的第一个机器学习模型
jvm·数据库·python