3

Generate Parentheses
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

For example, given n = 3, a solution set is:

"((()))", "(()())", "(())()", "()(())", "()()()"


Personally, I think
time complexity
= O(n! ) (not including time copying tmpStr), n is the input,
= O(n * n!) ( including time copying tmpStr).

space complexity
= O(n) (stack space usage),
= O(n) (stack + recursion space usage).

Code: Java
import java.util.List;
import java.util.ArrayList;
import java.util.Stack;

public class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> list = new ArrayList<String>();

        // Input checking.
        if (n <= 0) {
            list.add("");
            return list;
        }

        String tmpStr = "";
        for (int i = 0; i < n; i ++) tmpStr += "(";

        helper(n, tmpStr, 0, list);

        return list;
    }

    private void helper(int n, String tmpStr, int start, List<String> list) {
        // Base case.
        if (tmpStr.length() == 2 * n) {
            if (isValid(tmpStr)) list.add(tmpStr);
            return;
        }

        for (int i = start; i < tmpStr.length(); i ++) {
            // Have a try.
            tmpStr = tmpStr.substring(0, i + 1) + ")" + 
                     tmpStr.substring(i + 1, tmpStr.length());

            // Do recursion.
            helper(n, tmpStr, i + 1, list);

            // Roll back.
            tmpStr = tmpStr.substring(0, i + 1) + 
                     tmpStr.substring(i + 2, tmpStr.length());
        }
    }

    private boolean isValid(String str) {
        // Input checking.
        if (str == null || str.length() < 2) return false;

        Stack<Character> stack = new Stack<Character>();

        for (int i = 0; i < str.length(); i ++) {
            char curr = str.charAt(i);
            if (curr == '(') stack.push(curr);
            else {
                if (stack.isEmpty()) return false;
                stack.pop();
            }
        }

        if (stack.isEmpty()) return true;
        else return false;
    }
}
Zhaonan
  • 939
  • 1
  • 11
  • 20
  • 1
    Not really, using dynamic programming you would be able to do it in better time that O(n!). Example: for n = 5 `((rest))` and `(()rest)` and `(rest())` where rest is the generation for n == 3 and is the same in the 3 cases. Space complexity would be bigger but time complexity much better. – NetVipeC Aug 06 '14 at 20:16
  • 2
    @NetVipeC - if you only have to count the number of valid parenthesis arrangements, yes. If you have to actually compute/output all such arrangements, no. – candu Aug 06 '14 at 21:24
  • 4
    @BartKiers Actually, the catalan numbers are in O(4^n), so far less horrible than O(n!). – G. Bach Aug 06 '14 at 23:51
  • 1
    Thank you guys, the information is really useful, and @NetVipeC, you remind me that if we just need count the number of ways to generate valid parentheses, we actually can use DP, and I will have a try. For this problem, I hope to get a tight time complexity analysis, any help is welcoming. – Zhaonan Aug 07 '14 at 00:26
  • @G.Bach, yeah, you are right. After scrolling through [Wolfram's Catalan Numbers page](http://mathworld.wolfram.com/CatalanNumber.html), I see I was a bit too pessimistic :) – Bart Kiers Aug 07 '14 at 07:03
  • @candu Actually NetVipeC's solution also works for printing the results. Please see https://rekinyz.wordpress.com/2015/02/13/generate-parentheses/ for details. – luochenhuan Oct 04 '16 at 15:42

1 Answers1

2

If you could do a bit alteration in your validation method you can save a significant execution time for large value of n. You can use a counter instead of a stack to check for validation. something like this

 private boolean isValid(String str)
  {
    // Input checking.
    if (str == null || str.length() < 2)
    {
      return false;
    }
    int ct = 0;
    for (int i = 0; i < str.length(); i++)
    {
      char curr = str.charAt(i);
      if (ct < 0)
      {
        return false;
      }
      if (curr == '(')
      {
        ct++;
      }
      else if (curr == ')')
      {
        ct--;
      }
    }
    if (ct != 0 || ct < 0)
    {
      return false;
    }
    else
    {
      return true;
    }
  }

I ran it on my machine and the time saving for n=13 is around 2 sec and with this method in place the total execution time for the algorithm is less than 2 sec. For n=15 time saving is around 12 sec.

This will not only save time but will also save significant amount of memory.

Himanshu
  • 517
  • 1
  • 4
  • 13