洛谷 P1739 表达式括号匹配

P1739 表达式括号匹配

题目描述

假设一个表达式有英文字母(小写)、运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回“YES”;否则返回“NO”。表达式长度小于255,左圆括号少于20个。
输入输出格式

输入格式:

一行:表达式

输出格式:

一行:“YES” 或“NO”

输入输出样例

输入样例#1:

2*(x+y)/(1-x)@

输出样例#1:

YES

输入样例#2:

(25+x)(a(a+b+b)@

输出样例#2:

NO

括号配对问题可以通过栈来实现,我们可以把所有的左括号存入栈中,如果遇到了右括号,则判断栈顶是否存有左括号如果在存在右括号而栈空的情况或者栈不为空而输入已结束的情况就是不匹配,否则就是匹配
代码如下

#include<stdio.h>
#include<string.h>
#include<stack>
#include<algorithm>
using namespace std;
int main()
{	
	stack <char> s; //建一个栈 
 
	char ch;
 
 	int flag = 0;
 
 	while((ch = getchar()) != '@')    //读取字符并判断 
 	{
  		if(ch == '(')
  
   		s.push(ch);            //如果是左括号则入栈 
  
  		if(ch == ')')
  		{
   			if(s.empty())           //如果读入右括号时栈为空,则不匹配 
   			{
    				flag = 1;
    
    				break;
   			}
   			else
   			{
    				s.pop();              // 栈不为空,消除栈顶的括号 
   			}
  		}
 	}
 	if(s.empty()&&flag!=1)         //如果栈空了且没有中途不匹配的情况出现则证明匹配 
  
 	printf("YES\n");
 
 	if(flag==1||!s.empty())       //否则不匹配 
  
 	printf("NO\n");
}
<think>嗯,用户让我写一个程序来检查表达式中的圆括号是否匹配,用指针的方法。首先我得理解这个问题。题目中的表达式小写字母、运算符、左右圆括号组成,以@结束。需要检查括号是否匹配,输出YES或NO。比如输入例子里的第一个是正确的,第二个不匹配。 那怎么判断括号是否匹配呢?通常可以用栈结构来处理。遇到左括号入栈,遇到右括号出栈,如果栈空了还遇到右括号,或者最后栈不为空,就不匹配。但题目要求用指针的方法,可能是指用指针遍历字符串而不是显式使用栈结构?或者可能希望用指针操作来代替数组索引? 不过不管怎样,核心应该是栈的思想。那如果用指针的话,可能还是需要一个类似栈的结构,但用指针来操作这个栈。比如维护一个栈数组,然后用一个指针(比如int类型)指向栈顶。 首先,我需要读取输入的表达式,直到遇到@为止。注意题目里说表达式长度小于255,左括号少于20个,所以栈的大小可以设为20,足够用了。 步骤大概是这样的: 1. 初始化一个栈,用数组实现,栈顶指针初始化为-1或者0,根据具体实现而定。 2. 遍历表达式中的每个字符,直到遇到@。 3. 遇到左括号'('时,入栈。如果栈已满(因为题目说左括号少于20,所以栈的大小20应该够,但可能还是要判断,避免溢出?不过输入可能不符合条件,比如超过20个左括号,这时候程序也要处理,返回NO)。 4. 遇到右括号')'时,检查栈是否为空。如果为空,说明没有对应的左括号,直接返回NO。否则,出栈。 5. 遍历结束后,检查栈是否为空。如果为空,说明所有括号都匹配,否则不匹配。 那用指针的话,可以用一个指针变量来作为栈顶指针,比如int *top,或者直接用整型变量表示栈顶的位置。比如定义一个char数组stack[20],然后用int top = -1; 当遇到'('时,top++,stack[top] = '('。遇到')'时,如果top == -1,返回错误,否则top--。 这样其实是用数组模拟栈,而top变量类似于指针,指向栈顶。这可能符合题目中的“使用指针的方法”的要求吗?或者题目可能希望用指针来遍历字符串,而不是数组索引? 比如遍历字符串的时候,使用指针逐个移动,而不是用下标。比如: char *p = expression; while (*p != '@') { // 处理字符 p++; } 这可能更符合指针的方法。同时,栈的操作还是用数组和top变量,这应该可以。因为题目中的“指针的方法”可能指的是字符串处理部分用指针,而不是用索引。 所以整个思路是: - 使用指针遍历输入字符串。 - 用栈结构(数组和top变量)来跟踪括号匹配。 - 遇到左括号入栈,右括号检查栈是否为空,否则出栈。 - 最后检查栈是否为空。 然后需要考虑输入中的其他字符,比如字母、运算符,这些不需要处理,直接跳过。 现在考虑代码结构: 读取输入:可以用fgets读取一行,然后处理到@为止。或者在循环中逐个字符读取,直到遇到@。例如: char expr[256]; fgets(expr, 256, stdin); 然后找到第一个@的位置,或者遍历直到遇到@。 或者用scanf读取,但可能要考虑空格的问题。题目中的输入是一行表达式,可能包含空格吗?题目描述中没有提到,所以可能假设输入中没有空格,或者需要处理可能存在的空格?题目给出的例子输入1是"2*(x-y)/(1-×)@“,中间没有空格,所以可能不需要处理空格。 然后遍历每个字符: char *p = expr; while (*p != '@' && *p != '\0') { if (*p == '(') { // push if (top >= 19) { // 栈满,超过20个左括号? // 题目中说左括号少于20个,但输入可能不合法,这时候应该返回NO? printf("NO\n"); return 0; } stack[++top] = *p; } else if (*p == ')') { if (top == -1) { printf("NO\n"); return 0; } top--; } p++; } 最后,如果top == -1,输出YES,否则NO。 那这样的话,代码的大体结构是: #include <stdio.h> int main() { char expr[256]; scanf("%s", expr); // 这里可能有问题,因为scanf遇到空格会停止,但题目输入可能不含空格? // 或者用fgets读取整行,然后处理到@为止。 // 例如: fgets(expr, sizeof(expr), stdin); char stack[20]; int top = -1; char *p = expr; while (*p != '@' && *p != '\0') { if (*p == '(') { if (top >= 19) { // 栈已满,左括号超过19(因为索引从0开始) printf("NO\n"); return 0; } stack[++top] = *p; } else if (*p == ')') { if (top == -1) { printf("NO\n"); return 0; } top--; } p++; } // 检查是否还有剩余的左括号 if (top == -1) { printf("YES\n"); } else { printf("NO\n"); } return 0; } 那这样是否满足题意? 测试用例: 输入1:2*(x-y)/(1-×)@,处理到@为止。遍历每个字符,括号数量匹配,最后top=-1,输出YES。 输入2:(25+x)*(a*(a+b+6)@,左括号有三个,右括号只有两个。所以栈最后top=0,输出NO。 那这个代码是否符合要求? 需要注意的问题: 1. 输入中的@可能后面还有其他字符吗?题目说明以@作为结束符,所以遇到@就停止处理后面的字符。比如输入是"abc)@def",那么只处理到@之前的字符。 所以代码中的循环条件是当*p是@时停止。 2. 如何处理输入的读取?比如用scanf的话,如果表达式中有空格,scanf会停止读取,所以可能用fgets更安全。例如: fgets(expr, 256, stdin); 然后遍历expr中的每个字符,直到遇到@或者字符串结束符\0。 这样,即使输入中有空格,也能正确处理。 但假设用户输入的表达式正确,即以@结束,并且不包含换行符或其他问题。比如用户输入的是"..."@,后面可能有换行符,但fgets会读取到换行符。所以在循环中,只要检查到字符是@就停止处理。 例如,输入是"(a+b)@\n",那么循环在处理到@时停止,后面的换行符不会被处理。 所以代码中的循环是正确的。 另外,关于栈的大小,题目中给出左括号的数量少于20,所以栈的大小设为20足够。但用户输入可能不合法,有超过20个左括号,这时候在入栈的时候会检查top是否>=19(因为栈从0开始到19),如果是,说明栈满,此时无法再压入,直接返回NO。 例如输入是"((((...))",其中有21个左括号,那么在压入第20个的时候(top=19时),下一个左括号就会导致top变成20,这时候判断top >=19是否成立?原来的代码判断是if (top >=19),比如原代码中的条件: if (top >=19) { // 栈已满,左括号超过19(因为索引从0开始) 此时,当top是19时,还可以压入一个元素(因为stack[19]是最后一个位置)。当压入后,top变成19。下一个左括号进来时,top++变成20,此时判断是否>=19,是的,这时候返回NO。所以当左括号超过20个时,会正确返回NO。因为题目中左括号数目少于20,所以输入中如果有超过的,视为不合法,返回NO。 所以这部分处理是正确的。 综上,这个程序应该能正确处理问题,并且使用指针遍历字符串,栈结构来判断括号是否匹配。这样符合题目的要求吗?</think>要检查表达式中的圆括号是否匹配,可以使用栈的思想结合指针遍历字符串。以下是详细的实现步骤: ### 方法思路 1. **栈结构**:用数组模拟栈,维护栈顶指针跟踪括号状态。 2. **遍历字符串**:使用指针逐个字符处理表达式,直到遇到结束符 `@`。 3. **括号匹配**: - 遇到左括号 `(` 入栈。 - 遇到右括号 `)` 检查栈是否为空,若空则不匹配;否则出栈。 4. **最终检查**:遍历结束后,若栈为空则所有括号匹配。 ### 解决代码 ```c #include <stdio.h> int main() { char expr[256]; fgets(expr, sizeof(expr), stdin); // 读取整行输入 char stack[20]; // 栈用于存放左括号 int top = -1; // 栈顶指针初始化为-1 char *p = expr; // 指针遍历表达式 while (*p != '@' && *p != '\0') { if (*p == '(') { if (top >= 19) { // 左括号超过容量 printf("NO\n"); return 0; } stack[++top] = '('; // 入栈 } else if (*p == ')') { if (top == -1) { // 栈空无法匹配 printf("NO\n"); return 0; } top--; // 出栈 } p++; // 移动指针到下一字符 } // 最终栈为空则匹配成功 printf(top == -1 ? "YES\n" : "NO\n"); return 0; } ``` ### 代码解释 1. **输入处理**:使用 `fgets` 读取整行输入,避免空格问题。 2. **栈初始化**:`stack` 数组存储左括号,`top` 表示栈顶位置。 3. **指针遍历**:用指针 `p` 逐个字符检查: - **左括号**:压栈前检查是否超过容量(题目限制左括号少于20)。 - **右括号**:弹栈前检查栈是否为空,若空则立即返回不匹配。 4. **最终判断**:遍历结束后,若栈为空(`top == -1`)则输出 `YES`,否则 `NO`。 此方法时间复杂度为 $O(n)$,空间复杂度 $O(1)$(栈大小固定),能高效处理题目要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值