简体   繁体   中英

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. 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?

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. So:

If n=1 , then you can only do 1+(-1) . If n=2 , then can do 1+(-1)+1+(-1) or 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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