      "* Base case: `l = 0 and r = 0`\n",
      "    - Add the string generated to the result set\n",
      "* Case 1: `l > 0`\n",
      "    - Add a left parenthesis to the parentheses string.\n",
      "    - Call parentheses_util(l - 1, r, new_string, result_set)\n",
      "* Case 2: `r > l`\n",
      "    - Add a right parenthesis to the parentheses string.\n",
      "    - Call parentheses_util(l, r - 1, new_string, result_set)\n",
      "\n",
      "Complexity:\n",
 
</s> remove     "    - Call parentheses_util(l, r - 1, new_string, result_set)\n",
 </s> add     "    - Recurse (l, r - 1, new_string, result_set)\n", </s> remove     "* Time: `O(4^n/n^(3/2))`. See [Catalan numbers](https://en.wikipedia.org/wiki/Catalan_number#Applications_in_combinatorics)\n",
    "* Space complexity: `O(n)` (Due to the implicit call stack storing a maximum of 2n function calls)"
 </s> add     "* Time: `O(4^n/n^(3/2))`, see [Catalan numbers](https://en.wikipedia.org/wiki/Catalan_number#Applications_in_combinatorics) - 1, 1, 2, 5, 14, 42, 132...\n",
    "* Space complexity: `O(n)`, due to the implicit call stack storing a maximum of 2n function calls)" </s> remove     "def parentheses_util(no_left, no_right, pair_string, result):\n",
    "    if no_left == 0 and no_right == 0:\n",
    "        result.add(pair_string)\n",
    "    else:\n",
    "        if no_left > 0:\n",
    "            parentheses_util(no_left - 1, no_right, pair_string + '(', result)\n",
    "        if no_right > no_left:\n",
    "            parentheses_util(no_left, no_right - 1, pair_string + ')', result)\n",
 </s> add     "class Parentheses(object):\n", </s> remove     "def pair_parentheses(n):\n",
    "    result_set = set()\n",
    "    if n == 0:\n",
    "        return result_set\n",
    "    parentheses_util(n, n, '', result_set)\n",
    "    return result_set"
 </s> add     "    def _find_pair(self, nleft, nright, curr_results, results):\n",
    "        if nleft == 0 and nright == 0:\n",
    "            results.append(''.join(curr_results))\n",
    "        else:\n",
    "            if nleft >= 0:\n",
    "                self._find_pair(nleft-1, nright, curr_results+['('], results)\n",
    "            if nright > nleft:\n",
    "                self._find_pair(nleft, nright-1, curr_results+[')'], results)" </s> remove     "* None"
 </s> add     "\n",
    "* Is the input an integer representing the number of pairs?\n",
    "    * Yes\n",
    "* Can we assume the inputs are valid?\n",
    "    * No\n",
    "* Is the output a list of valid combinations?\n",
    "    * Yes\n",
    "* Should the output have duplicates?\n",
    "    * No\n",
    "* Can we assume this fits memory?\n",
    "    * Yes"
    "    - Recurse (l - 1, r, new_string, result_set)\n",
      "* Base case: `l = 0 and r = 0`\n",
      "    - Add the string generated to the result set\n",
      "* Case 1: `l > 0`\n",
      "    - Add a left parenthesis to the parentheses string.\n",
    "    - Recurse (l - 1, r, new_string, result_set)\n",
      "* Case 2: `r > l`\n",
      "    - Add a right parenthesis to the parentheses string.\n",
      "    - Call parentheses_util(l, r - 1, new_string, result_set)\n",
      "\n",
      "Complexity:\n",
keep keep keep keep replace keep keep keep keep keep
 Rework n pairs parens challenge (#145) 
recursion_dynamic/n_pairs_parentheses/n_pairs_parentheses_solution.ipynb