递归解
删括号
https://ac.nowcoder.com/acm/problem/21303
非曰能,好学。欢迎大家一起交流学习
题目描述
链接:https://ac.nowcoder.com/acm/problem/21303
给你一个合法的括号序列s1,每次你可以删除一个"()"
你可以删除0个或者多个"()"
求能否删成另一个括号序列s2
问题分析
看答案,大家都用的动态规划,这里提供一个递归解法。
括号可以批成一组一组的,如下图所示,s1被分为两组,s2只包括一组。
怎么分组呢?对字符串中的左括号右括号计数,相等的时候,即为一组的结束位置。为了使得s1能0个或者多个"()"变成s2,需要s1中从前往后去pk s2中的组,若是能pk过,则去pk下一组,类似于判定一个字符串是否为另一个字符串的子序列
那怎么判断s1中的一组括号能pk过s2中一组括号呢?显然如上图所示s1的第一组是干不过s2中括号组,但是s1的第二组可以干过s2中括号组。总结规律可以得到:将预对比的两组括号,分别去掉开头和结尾,pk剩下的两括号字符串,而pk剩下的两括号字符串即原问题本身,从而完成递归。
代码实现
最后附上本人拙劣的代码,耗时6ms,内存消耗相比动态规划小很多
#include <bits/stdc++.h>
using namespace std;
class Solution
{
public:
string s1;
string s2;
void read()
{
cin>>s1;
cin>>s2;
}
int getNext(const string& S, int is)
{
int lcnt=0;
int rcnt=0;
while(is<S.size())
{
if(S[is]=='(')
lcnt++;
else
rcnt++;
if(rcnt==lcnt)
return is;
is++;
}
return is;
}
// 多组原子对多组原子
bool isMatch(int l1, int r1, int l2, int r2)
{
int i1,i2,j1,j2;
j1=l1-1;
i2=l2;
j2=getNext(s2,i2);
while(j2<=r2)
{
while(1)
{
i1=j1+1;;
if(i1>r1)
return false;
j1=getNext(s1,i1);
if( isCover(i1,j1,i2,j2) )
{
i2=j2+1;
if(i2>r2)
return true;
j2=getNext(s2,i2);
break;
}
}
}
return true;
}
//s1的从l1到r1,能cover住s2的l2到r2吗, l1-l1是个原子,即(xxx)
bool isCover(int l1, int r1, int l2, int r2)
{
if(r1-l1<r2-l2)
return false;
if(l2+1==r2)
return true;
return isMatch(l1+1,r1-1, l2+1,r2-1);
}
void process()
{
read();
if(isMatch(0,s1.size()-1, 0, s2.size()-1))
cout<<"Possible"<<endl;
else
cout<<"Impossible"<<endl;
return ;
}
};
int main()
{
Solution s;
s.process();
return 0;
}
查看9道真题和解析