删除多余括号--蓝桥杯题目详解

题目

在这里插入图片描述

题目解析

关于去不去括号的探讨:

  1. 如果是(a+b)-c,发现括号可去,但是若(a+b)-(c+d)后面的括号括号又不可去。
  2. 若(ab)/c发现括号可去,但是(ab)/(c*d)后面的括号是不可去的。
  3. 经过大量对括号情况的枚举,我发现带括号的一般运算符的优先级是’/’ > ‘*’ > ‘-’ > ‘+’,若括号中最小的优先级比括号前后的优先级都要大或者是等于,则括号可去。而前两中情况就是单独列出来的特殊情况。
  4. 对特殊情况的说明:如果出现(a+b)-c,且 ‘(’ 前面的符号优先级小于等于 ‘+’,比如如果是a-(b+c)-d很明显括号不能去,但如果出现的是’ + ‘或者是’ ( '又或者前面没东西,这些情况都可以去掉括号,同理(a*b)/c也是如此

写代码的准备:

  1. 我们需要存储优先级,明显可以用hash表对运算符的映射得到。
  2. 我们需要判断括号内外的优先级,这里可以通过栈来进行相关操作。
  3. 我们需要删除括号,C++中可以直接把字符改为’\0’或者0,相当于删除了,因为string类是通过多次C风格的字符串拼接形成的。

其实有过数据结构栈的学习基础的,一般对括号相关的问题,应该都能想到去用栈来处理

逐行解析的代码

//整体思路:什么时候括号可去呢?括号中的最小优先级的运算符,它的优先级如果大于等于括号前后的优先级,括号可去。
#include <bits/stdc++.h>
using namespace std;
int main(){
    string s;
    //数组模拟hash
    int level[256];
    memset(level,0,sizeof(level));
//设置优先级,在带括号的优先级中,'/'明显优先级最高,而'+'优先级是最低的(这方面可以自己尝试)
    level['/']=4;level['*']=3;level['-']=2;level['+']=1;
    cin>>s;
        //把括号和其中的运算符的位置入栈进行相关操作
        stack<int> stack;
        for(int i=0;i<s.length();i++){
            if(s[i]=='(' || s[i]=='+' || s[i]=='-'
            || s[i]=='*' || s[i]=='/'){
                stack.push(i);
            }//一旦碰到右括号,开始出栈更新各优先级
            else if(s[i]==')'){
                int minLevel=5;
                //更新中间的最小优先级
                while(s[stack.top()]!='('){
                    minLevel = min(minLevel,level[s[stack.top()]]);
                    stack.pop();
                }
                //创建用于更新前后优先级的变量,默认优先级是最低的
                int before = -1;
                int after = -1;
                //判断后面是否有运算符,如果有更新优先级
                if(i+1<s.length() && s[i+1]!=')'){
                    after = level[s[i+1]];
                }
                //判断前面是否有运算符,如果有更新优先级
                if(stack.top()-1>=0 && s[stack.top()-1]!='('){
                    before = level[s[stack.top()-1]];
                }
                //中间的优先级满足同时大于或等于前后的优先级,则该括号可以去掉
                if(minLevel>=after && minLevel>=before){
//让s[i]=>右括号,s[stack.top()]=>左括号等于'\0'即可,
//因为在C++中string容器可以看作是多个字符串所拼接而成的,一旦遇到'\0'表示该段字符串结束,但还会继续读取后续被拼接的字符串,不然也是无法重载'+'运算符的。
                    s[i] = s[stack.top()] = 0;
                }//处理特殊情况:1.当(a+b)-y时括号可去,其中'('的前面必须是优先级小于等于'+'
                // 2. 当(x*y)/t括号可去,其中'('的前面优先级必须小于等于'*'
                //这两种虽不满足中间的优先级大于等于前后,但实际上可以转化为从左到右的运算,所以为特殊情况
                if((minLevel==1 && after==2 && before<=1)
                || (minLevel==3 && after==4 && before<=3)){
                    s[i] = s[stack.top()] = 0;
                }
                stack.pop();
            }
        }
        //输出结果
    cout<<s;
    
    return 0;
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值