给出一个正整数n,请给出所有的包含n个'('和n个')'的字符串,使得'('和')'可以完全匹配。
例如:
'(())()','()()()' 都是合法的;
'())()('是不合法的。
请按照__字典序__给出所有合法的字符串。
输入描述:
输入为1个正整数
输出描述:
输出为所有合法的字符串,用英文逗号隔开
示例1
输入
2
输出
(()),()()
思路:
可以采用暴力解法和深度优先遍历。
1.暴力法 :根据输入的n得到字符串的全排列(使用了std::next_permutation),然后排除不合法的,筛选出合法的字符串。具体筛选的方法可以借助栈,思路是遍历字符串,当遇到‘(’就入栈,当遇到‘)’就是出栈,判断是不是‘(’,如果是,则下一个,否则返回空串“”。特殊的,如果字符串第一个字符就遇到‘)’,此时栈还是空的,那么就直接返回空串“”。当循环结束,说明并没有返回空串“”,则说明该串合法,则返回当前的串。
2.深度优先遍历DFS:字符串总长度为2*n,当"("的个数小于n,则添加一个"(",并且总数加1;添加")"的规则苛刻一点,当")"的数目小于n,并且")"的数目小于"("时,才能添加")",这样才能保证有左括号可以匹配。
代码:
1.暴力解:
#include <iostream>
#include <algorithm>
#include <string>
#include <stack>
using namespace std;
string validStr(string ss){ //核心是遇到‘)’,看看之前有没有配对的‘(’.用到后进先出,所以考虑到
//用栈
stack<char> sc;
for (int i = 0; i < ss.size(); i++){
if (ss[i] == ')')
{
if (!sc.empty()){
char c = sc.top();
sc.pop();
if (c != '(')
return "";
}
else
return "";
}
else {
sc.push(ss[i]);
}
}
return ss;
}
int main(){
int n;
cin >> n;
string str = "";
for (int i = 0; i <n;i++)
{
str += "(";
}
for (int i = 0; i < n; i++)
{
str += ")";
}
string scopy(str); //这个合理字符串先输出,后续不输出。
cout << str ; //结果输出中第一个 ,后续输出都要加“,”+str的格式
string res ="";
do
{
res=validStr(str);
if (res != "" && res!=scopy) cout <<","<< res ;
} while (next_permutation(str.begin(),str.end()));
return 0;
}
2.深度优先遍历DFS
#include <iostream>
#include <algorithm>
#include <string>
#include <stack>
#include<vector>
using namespace std;
void DFS(int n,int x, int l, int r, string str, vector<string> &ret){
if (x == 2 * n){
ret.push_back(str);
return;
}
if (l < n) DFS(n,x + 1, l + 1, r,str+"(", ret);
if (r<n && l>r) DFS(n,x+1,l,r+1,str+")",ret);
return;
}
int main(){
vector<string> ret;
int n;
cin >> n;
DFS(n,0, 0, 0, "", ret);
cout << ret[0];
for (int i = 1; i < ret.size();i++)
{
cout << "," << ret[i];
}
return 0;
}