【LeetCode刷题记录】简单篇-20-有效的括号

【题目描述】 

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

有效字符串需满足:

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

【测试用例】

示例1:

        输入:s = "()"

        输出:true

示例2:

        输入:s = "()[]{}"

        输出:true

示例3

        输入:s = "(]"

        输出:false


【思路分析】

可能以前见过这个题目,我看到题目的第一时间想到的方法就是栈。

联想数学算式,比如{1×[2×(3-1)+1]-1},要先计算小括号,再计算中括号,最后计算大括号,那么就得先找到小括号的左括号,再找到小括号的右括号,计算出括起来的算式的结果;再找中括号的左括号,中括号的右括号....

换种理解方式,就是要完成括号配对的过程。当遇见一个左括号时(不论大/中/小括号的左括号),那么下一个括号只能有两种情况:

1.与该左括号相配对的右括号。此时可以直接删去配对成功的这两个括号,开始配对前一个左括号。

2.另一个新的左括号。此时这个新的左括号作为下一轮的待匹配括号。

不满足上述两种情况的均为匹配失败,直接返回false。

例如,遇见左括号1:{ 时,下一个匹配的只能是 '}' 或者新的左括号。上例中,下一个匹配到新的左括号2:( ,则2号更新为待匹配括号,那么下一个括号只能是与2号配对的 ')' 或者新的左括号。下一个括号3与括号2配对成功,直接删去括号2、3,开始配对前一个左括号,也就是括号1。括号1的下一个括号4是个左括号,更新为待匹配括号,需要 ']' 或者新的左括号;继续往后5号是新的左括号,更新为待匹配括号,需要 ')' 或者新的左括号;下一个括号6与括号5配对成功,删去,开始配对左括号4;下一个括号7与括号4匹配,删去,开始配对左括号1;下一个括号8与括号1匹配,删去。当遍历到最后一个括号,且前面的所有括号都被删去之后,说明配对成功,返回true。

上述过程实际上非常符合栈的特点:后进先出。后入栈的左括号要先被匹配。具体实现方式:遇见左括号直接入栈,遇见右括号则取出栈顶的左括号,如配对成功,遍历下一个括号,如配对失败,直接返回false。当所有括号都遍历完后,如果栈为空,则表示所有括号都匹配成功,返回true。


【参考代码】

C实现

#include <stdio.h>
#include <string.h>
#include <stdbool.h> 

//easy-20-有效的括号 
bool isValid(char* s);
char match(char c);

int main(){
	char s[100];
	scanf("%s",s);
	bool res = isValid(s);
	if(res){
		printf("true");
	}else{
		printf("false");
	}
	return 0;
} 

bool isValid(char* s) {
    int top=0,i;
    char stack[strlen(s)];
    for(i=0;i<strlen(s);++i){
    	if(s[i]=='(' || s[i]=='[' || s[i]=='{'){
    		stack[top++]=s[i];
    		continue;
		}
		char ch = match(s[i]);
		if(top==0 || (ch!=stack[top-1])){
			return false;
		}else{
			top--;
		}
	}
	return top==0;
}

char match(char c){
	if(c==')'){
		return '(';
	}else if(c==']'){
		return '[';
	}else if(c=='}'){
		return '{';
	}
}

C++实现

在C中,使用一个函数match来实现括号的对应。而在C++中,使用容器unordered_map来实现,可以提高代码的可扩展性。另一方面,C++的STL中有现成的函数,更加简化。

#include <iostream>
#include <unordered_map>
#include <stack>
#include <string> 
using namespace std;

//easy-20-有效的括号
class Solution {
public:
    bool isValid(string s);
}; 

bool Solution::isValid(string s){
	int i;
    unordered_map<char, char> match={
		{')','('},
		{']','['},
		{'}','{'}
	}; 
	stack<char> stack;
    for(i=0;i<s.size();++i){
    	if(s[i]=='(' || s[i]=='[' || s[i]=='{'){
    		stack.push(s[i]);
    		continue;
		}
		char ch = match[s[i]];
		if(stack.empty() || (ch!=stack.top())){
			return false;
		}else{
			stack.pop();
		}
	}
	return stack.empty();
}

int main(){
	Solution sol;
	string s;
	cin>>s;
	bool res = sol.isValid(s);
	if(res){
		cout<<"true"<<endl;
	}else{
		cout<<"false"<<endl;
	}
	return 0;
}

  • 38
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值