Java 了解多个递归调用的用例
我试图解决一个问题,在给定一个整数的情况下,得到所有可能的有效括号组合。例如,Java 了解多个递归调用的用例,java,recursion,dynamic-programming,Java,Recursion,Dynamic Programming,我试图解决一个问题,在给定一个整数的情况下,得到所有可能的有效括号组合。例如,输入:n=2,输出:(()),(()) 显然,随着n的增加,当前输出建立在前一个n的输出的基础上。因此,通过获取前面的结果并将其相加以获得当前结果,很容易得出递归结果: HashSet<String> getCombinations(int n) { HashSet<String> result = new HashSet<String>(); if (n <=
输入:n=2,输出:(()),(())
显然,随着n
的增加,当前输出建立在前一个n的输出的基础上。因此,通过获取前面的结果并将其相加以获得当前结果,很容易得出递归结果:
HashSet<String> getCombinations(int n)
{
HashSet<String> result = new HashSet<String>();
if (n <= 0) return null;
if (n == 1)
{
result.add("()");
return result;
}
for (String str: getCombinations(n - 1))
{
for (int i = 0; i < str.length(); i++)
{
result.add(new StringBuffer(str).insert(i, "()").toString());
}
}
return result;
}
HashSet-getcombines(int-n)
{
HashSet result=新的HashSet();
如果(n右)返回;
如果(nLeft==0&&nRight==0)
{
结果:添加(str);
返回;
}
getCombinations(索引+1,nLeft-1,nRight,新的StringBuffer(str).insert(索引,“(”).toString());
getcompositions(索引+1,nLeft,nRight-1,新的StringBuffer(str).insert(索引“)”).toString();
}
我理解这个解决方案是如何工作的,以及为什么它比第一个更好。但即使是现在,我也无法想象先看到第一个解决方案,然后再想到第二个解决方案。我如何直观地理解何时使用多个递归调用?换句话说,在实现了解决方案1之后,我怎么能认为使用多个递归调用可能会更好呢
我的问题不是针对上述问题,而是一般问题的类型。您可以将此问题视为1和-1的排列,当将其相加时,运行总和(从左到右相加时的临时值)不得小于0,或者如果是圆括号,右括号不能多于左括号。 因此: 如果
n=1
,则只能执行1+(-1)
。
如果n=2
,则可以执行1+-1)+1+-1
或1+1+-1+-1
因此,当您创建这些排列时,您会发现在每个递归调用中只能使用这两个选项中的一个,即
1
或-1
,并且通过跟踪nLeft
和nRight
使用的内容,您可以让程序知道何时停止 我想你是在试图解释上述解决方案是如何工作的。这不是我要问的。我理解逻辑和停止条件等。我不理解的是我如何直觉地从解决方案1跳到解决方案2。我怎么能想到“嗯,在这种情况下,我最好使用多个递归调用”。这不是一个容易问的问题:)好吧,一旦你明白你只能附加两个函数中的一个——或者(
或者)
,你就会发现这是一个二叉树,你需要多次递归调用来探索所有的叶子。如何从解决方案1跳到解决方案2只是选择了不同的方法。我无法将这个问题想象为一个二叉树。你能详细说明一下吗?我想关键的提示是“分而治之”。()它通常意味着多次递归调用。我不确定我是否同意。我认为这更多地属于动态规划领域,而不是分而治之,尽管我可能错了。就像合并排序是分而治之-我可以将问题清楚地划分为两个子问题,并最终合并结果。这里的情况似乎不是这样。我没有把输入像这样插入2。你确定吗?在我看来,你把你的问题分为两个问题:左手边的问题和右手边的问题。不,我不完全确定。这就是我在这里发帖的原因。虽然我觉得不是。当我考虑合并排序或矩阵乘法时,我清楚地将输入问题分为2,求解和合并。虽然这里似乎不是这样,或者至少(对我来说)不明显!
ArrayList<String> result = new ArrayList<>();
void getCombinations(int index, int nLeft, int nRight, String str)
{
if (nLeft < 0 || nRight < 0 || nLeft > nRight) return;
if (nLeft == 0 && nRight == 0)
{
result.add(str);
return;
}
getCombinations(index + 1, nLeft - 1, nRight, new StringBuffer(str).insert(index, "(").toString());
getCombinations(index + 1, nLeft, nRight - 1, new StringBuffer(str).insert(index, ")").toString());
}