题目描述:
/**
合法的括号匹配序列被定义为:
1. 空串""是合法的括号序列
2. 如果"X"和"Y"是合法的序列,那么"XY"也是一个合法的括号序列
3. 如果"X"是一个合法的序列,那么"(X)"也是一个合法的括号序列
4. 每个合法的括号序列都可以由上面的规则生成
例如"", "()", "()()()", "(()())", "(((())))"都是合法的。
东东现在有一个合法的括号序列s,
一次移除操作分为两步:
1. 移除序列s中第一个左括号
2. 移除序列s中任意一个右括号.保证操作之后s还是一个合法的括号序列
东东现在想知道使用上述的移除操作有多少种方案可以把序列s变为空
如果两个方案中有一次移除操作移除的是不同的右括号就认为是不同的方案。
例如: s = "()()()()()",输出1, 因为每次都只能选择被移除的左括号所相邻的右括号.
s = "(((())))",输出24, 第一次有4种情况, 第二次有3种情况, ... ,依次类推, 4 * 3 * 2 * 1 = 24
输入描述:
输入包括一行,一个合法的括号序列s,序列长度length(2 ≤ length ≤ 20).
输出描述:
输出一个整数,表示方案数
输入例子1:
(((())))
输出例子1:
24
*/
思路如下:
方案一:
观察题目给出的例子计算:
设str为k个(连续开头,且str合法
那么str
一定是 ((...()合法串)...合法串)
那么按着题目操作去掉第一个(,后面有k个)可以去掉
但是不能去掉合法串中的)否则就会非法
而且去掉k个后的)的新的串合法,而且是同样性质,都是k-1个(连续开头的新串,
那么基于这种原理,那么就可以维护一个指针计算当前最左端连续去掉的个数即可
方案二:
DFS时间最坏复杂度O(len2^(len+1))
加上记忆化空间复杂度O(2^(len+1)len)
代码如下:
#include<stdio.h>
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main(){
string str;
cin>>str;
int left_cnt=0, res=1;
for(int i=0; i<str.size(); i++){
if(str[i]=='('){
left_cnt++;
}
else if(str[i]==')'){
res*=left_cnt;//删除最左边的一个(可以产生更多的left_cnt字串,再运用乘法原理
left_cnt--;//删除最左边的一个
}
else{
return -1;
}
}
printf("%d", res);
return 0;
}
网友评论