嗨,从着名的Code to Crack一书中,我遇到了一个问题:
实施算法以打印n对括号的所有有效(例如,正确打开和关闭)组合。
实施例:
input: 3 (e.g., 3 pairs of parentheses)
output: ()()(), ()(()), (())(), ((()))
#include <iostream>
#include <string>
using namespace std;
void _paren(int l,int r,string s,int count);
void paren(int n)
{
string s="";
_paren(n,n,s,n);
}
void _paren(int l,int r,string s,int count){
if(l<0 || r<0)
return;
if(l==0 && r==0)
cout<<s<<endl;
else{
if(l>0)
{
_paren(l-1,r,s+"(",count+1);
}
if(r>l)
_paren(l,r-1,s+")",count+1);
}
}
int main(){
int n;
cin>>n;
paren(n);
return 0;
}
这是我尝试过的递归方法。我很确定我们也可以通过动态编程来解决这个问题,因为我们已经一次又一次地使用了很多价值,但我不知道如何通过动态编程实现这一点我尝试了表格自下而上的方法但是无法解决。请帮我解释一下如何使用这个
的基本想法答案 0 :(得分:2)
DP并没有真正帮助你。递归算法是时间和空间的最佳选择!
事实上,有一个理由不使用DP:内存要求!这将是巨大的。
更好的算法是让你传入一个字符数组,让递归方法修改它的一部分并在需要时打印它。我相信你在提到的那本书中给出了解决方案。
答案 1 :(得分:1)
DP可以通过为每次调用选择最佳解决方案来减少遍历状态的计数。它还可以帮助您重用计算值。没有计算,必须访问每个有效状态,if()可以避免无效状态。
我建议你实现另一个递归(至少在调用后不复制新的字符串对象,只需声明全局字符串数组并在需要时将其发送到输出)。
我对递归的想法是
char arr[maxN]; int n; // n is string length, must be even though
void func(int pos, int count) { // position in string, count of opened '('
if( pos == n ) {
for(int i = 0; i < n; i++)
cout << char(arr[i]);
cout << "\n";
return;
}
if( n-pos-1 > count ) {
arr[pos] = '('; func(pos+1,count+1);
}
if( count > 0 ) {
arr[pos] = ')'; func(pos+1,count-1);
}
}
我没有检查过,但我认为这个想法很明确。