简体   繁体   English

了解多个递归调用的用例

[英]Understanding the usecase of multiple recursive calls

I was trying to solve a problem to get all the possible valid combinations of parenthesis given an integer. 我正在尝试解决一个问题,以便在给定整数的情况下获得所有可能的有效括号组合。 Eg. 例如。 input: n = 2, output: (()), ()()

Clearly as n increases, the current output builds on the output of the previous n. 显然,随着n增加,当前输出建立在前n个的输出之上。 So it was easy to come up with a recursive by taking the previous result and adding to it to get the current result: 因此,通过获取先前的结果并将其添加以获得当前结果,很容易得出一个递归:

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

Though obviously the downside of the above code is the repetition of the same result values which are produced but not stored. 尽管显然上述代码的缺点是重复产生但未存储的相同结果值。 So I looked online for a better solution (as I could not think of it), and found this: 因此,我在网上寻找了更好的解决方案(因为我无法想到),并发现了这一点:

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

I understand how this solution works and why its better than the first. 我了解此解决方案的工作原理,以及为什么它比第一个更好。 But even now I cannot imagine looking at the first solution and then coming up with second solution. 但是即使到现在,我也无法想象先解决第一个解决方案,然后提出第二个解决方案。 How can I intuitively understand so as to when to use multiple recursive calls? 如何直观地理解何时使用多个递归调用? In other words, after achieving solution 1, how can I come to think that I would probably be better off with multiple recursive calls? 换句话说,在获得解决方案1之后,我怎么能认为多次递归调用可能会更好呢?

My question is not specific to the above problem, but the type of problems in general. 我的问题不是上述问题特有的,而是一般问题的类型。

You could look at this problem as permutations of 1 and -1, which while being summed together, the running sum (temp value while adding up numbers left-to-right) must not become less than 0, or in case of parenthesis, must not use more right-parenthesis than left ones. 您可以将这个问题看做1和-1的排列,将它们相加在一起时,运行总和(温度值,从左至右加总的温度)不得小于0,或者在括号的情况下必须不要使用比左括号更多的右括号。 So: 所以:

If n=1 , then you can only do 1+(-1) . 如果n=1 ,则只能执行1+(-1) If n=2 , then can do 1+(-1)+1+(-1) or 1+1+(-1)+(-1) . 如果n=2 ,则可以做1+(-1)+1+(-1)1+1+(-1)+(-1)

So, as you create these permutations, you see you can only use only one of the two options - either 1 or -1 - in every recursive call, and by keeping track of what has been used with nLeft and nRight you can have program know when to stop. 因此,在创建这些排列时,您会看到在每个递归调用中只能使用两个选项之一( 1-1 ,并且通过跟踪nLeftnRight使用的nLeft ,可以使程序知道什么时候停止。

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

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