Bad Sequence

题意

输入n个括号(只有左括号和右括号两种),最多允许移动一个括号,问能否实现括号匹配。

分析

这个题令我比较恼火,想多了,自己思路固定在用栈匹配中出不来了。
一开始想的是,先进行匹配,如果某种括号剩下两个,即可经过移动达到要求。这个需要单独考虑右括号在开头的情况。不知道为什么,我的代码总是错误。只好重换思路

错误代码

#include<bits/stdc++.h>
using namespace std;
stack<int>q;
int main()
{
    int i,j;
    int cnt=0,num1=0,num2=0,flag=0;
    string ch;
    scanf("%d",&i);
    cin>>ch;
    for(j=0;j<i;j++)
    {
    	if(ch[j]==')')
    	num1++;
    	else
    	num2++;
    }
    if(i==2)
    {
    	printf("Yes\n");
    	return 0;
    }
    int temp;
    temp=abs(num1-num2);
    if(temp!=2&&temp!=0)
	{
		printf("No\n"); 
		return 0;
	}
	//printf("%d %d\n",num1,num2);
    for(j=0;j<i;j++)
    {   cnt++;
        if(ch[j]=='(')
        {
        	q.push(cnt);
        }
        if(ch[j]==')')
        {
            if(flag==0&&q.empty())
            {
            	flag=1;q.push(cnt);num1--;num2++;continue;
            }
            else if(flag==1&&q.empty())
            {
            	printf("No\n");
            	return 0;
            }
            q.pop();
            num1--;num2--;
        }
		if((num2==0)&&(num1==2||num1==0))
        {
       		printf("Yes\n");
       		return 0;
       	}
       	else if(num1==0&&(num2==2||num2==0))
       	{
       		printf("Yes\n");
       		return 0;
       	}
    }
    printf("No\n");
    return 0;
} 

后来借鉴了网上大神的思路。不用栈匹配,直接用num来标记。一个左括号要和一个右括号相对应,相当于消除。遇到左括号,num++;右括号,num- -。再用一个mm记录经过消除后,右括号最左边的位置。如果mm==-1,说明在尚未匹配的队列中,右括号在最前面,且其后面就是左括号。这样是可以经过移动后形成匹配的。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int mm,num=0,n;
	char ch[200050];
	cin>>n>>ch;
	int i,j;
	mm=n;
	for(i=0;i<n;i++)
	{
		if(ch[i]=='(')
		num++;//相当于压栈,将左括号压入栈中
		else
		num--;//相当于出栈,每次最后压入的左括号都与第一个右括号相抵消
		mm=min(mm,num);//记录抵消后的第一个右括号的位置
	}
	if(num==0&&mm>=-1)//左右括号相等并且可以移动匹配
	printf("Yes\n");
	else
	printf("No\n");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值