【算法-LeetCode】20. 有效的括号(栈)

20. 有效的括号 - 力扣(LeetCode)

发布:2021年7月31日24:02:31

问题描述及示例

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。

示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
示例 4:
输入:s = “([)]”
输出:false
示例 5:
输入:s = “{[]}”
输出:true
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

提示:
1 <= s.length <= 104
s 仅由括号 ‘()[]{}’ 组成

我的题解(栈)

更新:2021年7月31日00:12:28

这道题思路不算复杂,我一开始是想取巧,想着能不能将输入的s进行reverse操作,然后将操作结果与原来的s做比较,如果一样的话就返回true,否则返回false。但是很快,我看到了第2个示例,发现这样不行。没过多久,我又想到了用栈的思想。

总体思路就是利用辅助栈matchStack存储origin中的右括号(当然存左括号也行,相应的地方也得改就是了),如果origin的栈顶元素为右括号,则直接压入matchStack;如果origin的栈顶元素为左括号,则需要判断该元素是否和matchStack的栈顶元素相匹配,如果左右括号匹配成功,则将matchStack中的栈顶元素弹出(突然想到,其实此时就可以返回false结果了,这也能在一定程度上提高一点效率)。将origin中的所有括号都遍历之后,如果两个栈均为空,说明所有括号都有相应的符合规则的匹配,当且仅当这种情况下可以返回true,其他情况均返回false

大致过程可看下方示意图。

20.有效的括号

/**
* @param {string} s
* @return {boolean}
*/
var isValid = function (s) {
	// 先将原始字符串转化为字符数组以便后续进行内容修改(字符串本身并不支持)
    let origin = s.split('');
    // 由于是将数组末尾作为栈的出口(栈顶),所以设置一个变量来存储所有可能的右括号
    let rightBrackets = [')', '}', ']'];
    // 下面这个判断其实可有可无,我觉得加上之后多少可以提高效率,毕竟做了提前返回的操作
    // 如果字符的第一位就是一个右括号或者字符的长度为奇数,则必然不能完全匹配,可提前返回
    if (rightBrackets.includes(origin[0]) || origin.length % 2 !== 0) {
        return false;
    }
    // matchStack用作匹配的辅助栈
    let matchStack = [];
    // 注意下面的i的初始值和结束条件,这是题目中比较关键的地方,j用于动态指向origin栈顶
    for (let i = 0, len = origin.length, j = len - 1; i < len; i++, j--) {
    	// 若origin栈顶为右括号,则将其压入matchStack以备后用,
    	// 同时将origin栈顶元素弹出,并用continue提前结束本次循环进入下一次循环
        if (rightBrackets.includes(origin[j])) {
            matchStack.push(origin[j]);
            origin.pop();
            continue;
        }
        // 若matchStack栈顶元素与origin栈顶元素相互匹配,则将这对括号同时分别从两个栈中删除
        if (matchStack[matchStack.length - 1] === matchTheHalf(origin[j])) {
            matchStack.pop();
            origin.pop();
        } else {
        	// 更新:2021年7月31日01:55:32
			return false;
		}
    }
    // 将origin栈里的元素全部遍历完后,当且仅当两个栈里都没有元素了(都匹配完了)
    // 说明 s 是符合括号匹配规则的字符串,返回true
    if (matchStack.length === 0 && origin.length === 0) {
        return true;
    }
    // 除上面所说的的其他情况,均为不符合括号匹配规则,返回false
    return false;

	// matchTheHalf用于返回与某个左括号相匹配的右括号
    function matchTheHalf(bracket) {
        if (bracket === '(') return ')';
        if (bracket === '{') return '}';
        if (bracket === '[') return ']';
    }
};


提交记录
91 / 91 个通过测试用例
状态:通过
执行用时: 76 ms,在所有 JavaScript 提交中击败了82.80%的用户
内存消耗: 37.9 MB,在所有 JavaScript 提交中击败了83.93%的用户
时间:202173100:00:02

更新:202173101:55:32
在上面的代码中加入了一个 else 语句分支,发现时间性能提高了不少
执行用时:64 ms, 在所有 JavaScript 提交中击败了97.92%的用户
内存消耗:38.8 MB, 在所有 JavaScript 提交中击败了49.80%的用户

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

更新:2021年7月31日24:11:01

参考:有效的括号 - 有效的括号 - 力扣(LeetCode)

【更新结束】

有关参考

暂无

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值