繁体   English   中英

了解多个递归调用的用例

[英]Understanding the usecase of multiple recursive calls

我正在尝试解决一个问题,以便在给定整数的情况下获得所有可能的有效括号组合。 例如。 input: n = 2, output: (()), ()()

显然,随着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;
}

尽管显然上述代码的缺点是重复产生但未存储的相同结果值。 因此,我在网上寻找了更好的解决方案(因为我无法想到),并发现了这一点:

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());
}

我了解此解决方案的工作原理,以及为什么它比第一个更好。 但是即使到现在,我也无法想象先解决第一个解决方案,然后提出第二个解决方案。 如何直观地理解何时使用多个递归调用? 换句话说,在获得解决方案1之后,我怎么能认为多次递归调用可能会更好呢?

我的问题不是上述问题特有的,而是一般问题的类型。

您可以将这个问题看做1和-1的排列,将它们相加在一起时,运行总和(温度值,从左至右加总的温度)不得小于0,或者在括号的情况下必须不要使用比左括号更多的右括号。 所以:

如果n=1 ,则只能执行1+(-1) 如果n=2 ,则可以做1+(-1)+1+(-1)1+1+(-1)+(-1)

因此,在创建这些排列时,您会看到在每个递归调用中只能使用两个选项之一( 1-1 ,并且通过跟踪nLeftnRight使用的nLeft ,可以使程序知道什么时候停止。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM