括号序列(C++,Stack)

题目描述

定义如下规则:

  1. 空串是「平衡括号序列」
  2. 若字符串 S S S 是「平衡括号序列」,那么 [ S ] \texttt{[}S\texttt] [S] ( S ) \texttt{(}S\texttt) (S) 也都是「平衡括号序列」
  3. 若字符串 A A A B B B 都是「平衡括号序列」,那么 A B AB AB(两字符串拼接起来)也是「平衡括号序列」。

例如,下面的字符串都是平衡括号序列:

()[](())([])()[]()[()]

而以下几个则不是:

([])(())([()

现在,给定一个仅由 ()[]构成的字符串 s s s,请你按照如下的方式给字符串中每个字符配对:

  1. 从左到右扫描整个字符串。
  2. 对于当前的字符,如果它是一个右括号,考察它与它左侧离它最近未匹配的的左括号。如果该括号与之对应(即小括号匹配小括号,中括号匹配中括号),则将二者配对。如果左侧未匹配的左括号不存在或与之不对应,则其配对失败。

配对结束后,对于 s s s 中全部未配对的括号,请你在其旁边添加一个字符,使得该括号和新加的括号匹配。

输入格式

输入只有一行一个字符串,表示 s s s

输出格式

输出一行一个字符串表示你的答案。

样例 #1

样例输入 #1

([()

样例输出 #1

()[]()

样例 #2

样例输入 #2

([)

样例输出 #2

()[]()

提示

数据规模与约定

对于全部的测试点,保证 s s s 的长度不超过 100,且只含 ()[] 四个字符。

解题思路:

首先解释题意:题意并不是很清晰,这里进一步解释一下

题目要求最终得到的括号序列仍然是平衡括号序列,并不是说只要有能匹配的括号即可

就是说如果括号序列为

([)]

那么得出的结果应该是

()[()]

两个小括号是不能匹配的

这样我们可以想到用来实现代码

首先说明匹配机制:

int main()
{
	string str;
	stack<char> char_stack;
	cin >> str;
	int len = str.size();
	for (int i = 0; i < len; i++)
	{
		switch (str[i])
		{
		case '(':
			char_stack.push(str[i]);
			break;
		case '[':
			char_stack.push(str[i]);
			break;
		case ')':
		{
			if (char_stack.top() == '(')
			{
				char_stack.pop();
			}
		}
		case ']':
			if (char_stack.top() == '[')
			{
				char_stack.pop();
			}
		default:
			break;
		}
	}
}

这里可以采用两种方式实现题中要求的输出效果

要解决的核心问题就是如何区分已经匹配的括号和未匹配的括号

方法一:引入另一个匹配字符串

int main()
{
	string str, match_str = "";
	stack<char> char_stack, index_stack;
	cin >> str;
	int len = str.size();
	for (int i = 0; i < len; i++)
	{
		switch (str[i])
		{
		case '(':
			{
				char_stack.push(str[i]);
				index_stack.push(i);//如果匹配成功匹配,通过该索引对应元素修改状态
				match_str += ')';//默认状态是未匹配
				break;
			}
		case '[':
			{
				char_stack.push(str[i]);
				index_stack.push(i);//如果匹配成功匹配,通过该索引对应元素修改状态
				match_str += ']';//默认状态是未匹配
				break;
			}
		case ')':
			{
				if (!char_stack.empty() && char_stack.top() == '(')//注意:一定要先判断栈是否为空
				{
					char_stack.pop();
					match_str[index_stack.top()] = '\0';//修改状态为已经匹配
					index_stack.pop();
					match_str += '\0';
				}
				else
				{
					match_str += '(';
				}
				break;
			}
		case ']':
			{
				if (!char_stack.empty() && char_stack.top() == '[')//注意:一定要先判断栈是否为空
				{
					char_stack.pop();
					match_str[index_stack.top()] = '\0';//修改状态为已经匹配
					index_stack.pop();
					match_str += '\0';
				}
				else
				{
					match_str += '[';
				}
				break;
			}
		default:
			break;
		}
	}
}

然后实现输出的代码如下

for (int i = 0; i < len; i++)
	{
		if (match_str[i] == '\0')//如果str[i]的状态为已匹配
		{
			cout << str[i];
		}
		else//如果str[i]的状态为未匹配
		{
			if (match_str[i] == '[' || match_str[i] == '(')
			{
				cout << match_str[i] << str[i];
			}
			else
			{
				cout << str[i] << match_str[i];
			}
		}
	}

方法一实现完成

(ps:如果超时的话可能是由于字符串的拼接操作耗费时间,可以尝试字符数组)

方法二:通过值的修改来修改括号的状态,如未匹配的括号值为1,已匹配的括号值为2

方法二的完整代码如下

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

int main()
{
	string str;
	cin >> str;
	stack<char> char_stack, index_stack;
	int len = str.size();
	for (int i = 0; i < len; i++)//共有六种状态:1-(),2-[],3-(,4-),5-[,6-]
	{
		switch (str[i])
		{
		case '(':
		{
			char_stack.push(str[i]);
			index_stack.push(i);//如果匹配成功匹配,通过该索引对应元素修改状态
			str[i] = 1;//默认状态是未匹配
			break;
		}
		case '[':
		{
			char_stack.push(str[i]);
			index_stack.push(i);//如果匹配成功匹配,通过该索引对应元素修改状态
			str[i] = 2;//默认状态是未匹配
			break;
		}
		case ')':
		{
			if (!char_stack.empty() && char_stack.top() == '(')//注意:一定要先判断栈是否为空
			{
				char_stack.pop();
				str[index_stack.top()] = 3;//修改状态为已经匹配
				index_stack.pop();
				str[i] = 4;
			}
			else
			{
				str[i] = 1;
			}
			break;
		}
		case ']':
		{
			if (!char_stack.empty() && char_stack.top() == '[')//注意:一定要先判断栈是否为空
			{
				char_stack.pop();
				str[index_stack.top()] = 5;//修改状态为已经匹配
				index_stack.pop();
				str[i] = 6;
			}
			else
			{
				str[i] = 2;
			}
			break;
		}
		default:
			break;
		}
	}
	for (int i = 0; i < len; i++)
	{
		switch (str[i])
		{
		case 1:
			cout << "()";
			break;
		case 2:
			cout << "[]";
			break;
		case 3:
			cout << '(';
			break;
		case 4:
			cout << ')';
			break;
		case 5:
			cout << '[';
			break;
		case 6:
			cout << ']';
			break;
		default:
			break;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WitheredSakura_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值