Leetcode 22. Generate Parentheses - 生成指定数量的有效圆括号,比如输入2,输出()()(())

Posted 二十六画生的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode 22. Generate Parentheses - 生成指定数量的有效圆括号,比如输入2,输出()()(())相关的知识,希望对你有一定的参考价值。

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

Example 1:

Input: n = 3
Output: ["((()))","(()())","(())()","()(())","()()()"]

Example 2:

Input: n = 1
Output: ["()"]

Constraints:

  • 1 <= n <= 8

https://leetcode.com/problems/generate-parentheses/solution/

看了给定的Solution,方法1、2、3,真是难懂,全是递归.....

自己琢磨出的求解方法,非递归,容易理解很多! 

我的方法(本文的方法1): 先设置n=1,保存好();从n=2开始,依赖上次生成的括号字符串,遍历每个括号字符串和其中的每个括号字符,生成本次的括号字符串,再把本次的结果用于计算下次的,如此循环。

字符串拼接:用StringBuilder比"String+A+B+C"的运行时间有所缩短,效率有所提高。

package com.string;

import java.util.*;

/**
 * @Author you guess
 * @Date 2022/4/10 21:41
 * @Version 1.0
 * @Desc 生成指定数量的有效圆括号 2->()()、(())
 */
public class Leetcode_22_Generate_Parentheses 

    /**
     * 方法1:优化后
     * Runtime: 24 ms, faster than 5.08% of Java online submissions for Generate Parentheses.
     * Memory Usage: 45.4 MB, less than 10.08% of Java online submissions for Generate Parentheses.
     *
     * @param n
     * @return
     */
    public List<String> generateParenthesis(int n) 
        List<String> list1 = new ArrayList<>();//存储总的结果
        list1.add("()");
        if (n == 1) 
            return list1;
        

        //n=2 3 4 ...
        for (int i = 2; i <= n; i++) 
            Set<String> set = new HashSet<>();//存储当次的结果
            for (int j = 0; j < list1.size(); j++) 
                String s = list1.get(j);
                // set.add("()" + s);//左,多余的
                // set.add(s + "()");//右,多余的
                set.add("(" + s + ")");//外
                set.addAll(this.addParenthesis(s));
            
            list1 = new ArrayList<>(set);
        
        return list1;
    

    /**
     * 优化后
     */
    public Set<String> addParenthesis(String s) 
        Set<String> set = new HashSet<>();
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) 
            StringBuilder sb = new StringBuilder();
            char c = s.charAt(i);
            if (c == '(') 
                //()()(()) -> (()())(()),这个比较容易忘记!!
                if (stack.isEmpty()) 
                    sb.append("(").append(s, 0, i).append(")").append(s.substring(i));
                    set.add(sb.toString());
                    //set.add("(" + s.substring(0, i) + ")" + s.substring(i));
                
                stack.push(i);
             else 
                int left = stack.pop();
                int right = i;
                //在里面加一层(),比如([待加入])() -> ([()])()
                sb.append(s, 0, left + 1).append("(").append(s, left + 1, right).append(")").append(s.substring(right));
                set.add(sb.toString());
                //set.add(s.substring(0, left + 1) + "(" + s.substring(left + 1, right) + ")" + s.substring(right));
            
        
        return set;
    


    class Entry 
        Character c;
        Integer index;

        public Entry(Character c, Integer index) 
            this.c = c;
            this.index = index;
        
    

    /**
     * 这个也正确,不过不必使用Entry类
     * 未优化
     *
     * @param s
     * @return
     */
    public Set<String> addParenthesisUseEntry(String s) 
        Set<String> set = new HashSet<>();
        Stack<Entry> stack = new Stack<>();

        for (int i = 0; i < s.length(); i++) 
            char c = s.charAt(i);
            if (c == '(') 
                //()()(()) -> (()())(()),这个比较容易忘记!!
                if (stack.isEmpty()) 
                    set.add("(" + s.substring(0, i) + ")" + s.substring(i));
                
                Entry leftEntry = new Entry(s.charAt(i), i);
                stack.push(leftEntry);
             else 
                Entry leftEntry = stack.pop();
                int left = leftEntry.index;// int left = leftEntry.getIndex() ; 同义
                int right = i;
                set.add(s.substring(0, left + 1) + "(" + s.substring(left + 1, right) + ")" + s.substring(right));
            
        
        return set;
    


    /**
     * Wrong Answer
     * <p>
     * Input
     * 4
     * Output
     * ["()()()()","(()()())","()(()())","(()())()","((()()))","()()(())","()(())()","(()(()))","()(())()","(())()()","((())())","()((()))","((()))()","(((())))"]
     * Expected
     * ["(((())))","((()()))","((())())","((()))()","(()(()))","(()()())","(()())()","(())(())","(())()()","()((()))","()(()())","()(())()","()()(())","()()()()"]
     * <p>
     * 结果:
     * 缺少"(())(())"
     * 输出了2个"()(())()"
     *
     * @param n
     * @return
     */
    public List<String> generateParenthesisWrong(int n) 
        List<String> list1 = new ArrayList<>();
        list1.add("()");
        if (n == 1) 
            return list1;
        

        //n=2 3 4 ...
        for (int i = 2; i <= n; i++) 
            List<String> list2 = new ArrayList<>();
            for (int j = 0; j < list1.size(); j++) 
                if (j == 0) 
                    list2.add(list1.get(j) + "()");//右
                    list2.add("(" + list1.get(j) + ")");//外
                 else 
                    list2.add("()" + list1.get(j));//左
                    list2.add(list1.get(j) + "()");//右
                    list2.add("(" + list1.get(j) + ")");//外
                
            
            list1 = list2;
        
        return list1;
    


    /**
     * Wrong Answer
     * 6
     * Output
     * [()(()())(()), ()((()))()(), ()(((())))(), (()((())))(), ((()()(()))), ()(())(())(), (()(()))()(), (()())(())(), ((())(()))(), (((())())()), ((()))()()(), ()((())())(), (((()())())), (()(())())(), ((()(())))(), (()()()()()), ((()))(())(), (()(()(()))), (())()(()()), ()(()(()())), ()()()()()(), ()((()())()), (()()(()))(), (((()))())(), ((()()()())), ()(())()()(), (())((()))(), ((()())())(), (())(()(())), (()(())()()), ((((()))())), (((())(()))), (()((())())), (()()()(())), ()()(())(()), (()())((())), ((((()())))), ()()()(())(), (())()(())(), (()(((())))), (((()()()))), ()()((())()), ()(((()()))), ((())()(())), (()(()()())), ()((()()())), ((()())()()), ()((())(())), ((())((()))), ()(()())()(), ()(((()))()), ((())())(()), ((()(())())), ((()()))()(), ()(())(()()), ()((()(()))), ((()))((())), ()(()()()()), (()()(())()), ((())(())()), ((()((())))), ()(()(()))(), (((()))(())), ()()(()(())), ((()()()))(), (())((()())), (()()())(()), (())(()())(), (((((()))))), (())()()()(), ()()(((()))), ((((()))))(), (((())))(()), (((()()))()), ((())())()(), (()()()())(), (())(((()))), ()()()((())), ()(()(())()), (())()((())), ()(())()(()), ((())()())(), (()(()()))(), ()((()()))(), (()())()(()), (())(()()()), ()((()))(()), (()((()()))), (()()())()(), (())(())()(), (((())()())), ((()))()(()), ((()(()()))), ()(()()())(), ()()((()())), ()()(()())(), (()()((()))), ((()(()))()), ()(((())())), ((()()))(()), ((()))(()()), ()(())((())), ((())()()()), (())(())(()), ()((((())))), ((())(()())), ((()()())()), ()()()()(()), ((((())()))), (())((())()), ()()(()()()), (()((()))()), (())()()(()), (((()())))(), (()(())(())), ()()(())()(), (((())))()(), ((((())))()), (((()))()()), (((()(())))), ()()()(()()), (()(()))(()), (((())()))(), (()()(()())), ()(()()(())), ()()((()))(), (()(()())()), ()((())()()), ((()())(())), (()())()()(), ()(()((())))]
     * Expected
     * [(())()(())()(), (())(((()))()), (())((()(()))), (())((()))(()), (())()()(()()), (())(()(()))(), (())()(()()()), (())(()(()())), (())()((()))(), (())()((()())), (())(()()()()), (())(((()()))), (())()()()()(), (())((()())()), (())(())()()(), (())()(()())(), (())(()(())()), (())()(()(())), (())(((())))(), (())(((())())), (())(()())(()), (())()(((()))), (())(()((()))), (())(())(())(), (())(())((())), (())()(())(()), (())()()(())(), (())()()((())), (())((()))()(), (())((())()()), (())((((())))), (())((()()())), (())(()()())(), (())(()()(())), (())()((())()), (())(())()(()), (())((()()))(), (())((())())(), (())()()()(()), (())((())(())), (())(())(()()), (())(()())()(), (())()()()(), (())(()())(), (())(()(())), (())()()(()), (())(())()(), (())(((()))), (())(())(()), (())()((())), (())()(())(), (())()(()()), (())(()()()), (())((()())), (())((()))(), (())((())()), (()())()()(), (()())(()()), (()())()(()), (()())(())(), (()())((())), ((()))()()(), ((()))(()()), ((()))()(()), ((()))(())(), ((()))((())), (()()())()(), (()()())(()), ((()()))()(), ((()()))(()), (()(()))()(), (()(()))(()), ((())())()(), ((())())(()), (((())))()(), (((())))(()), (()()()())(), ((()())())(), ((()(())))(), (()()(()))(), ((())()())(), ((((()))))(), ((())(()))(), (()((())))(), (()(())())(), (()(()()))(), ((()()()))(), (((()())))(), (((()))())(), (((())()))(), (()(())()())(), ((((()))()))(), (((()(()))))(), (((()))(()))(), (()()(()()))(), ((()(()))())(), (()(()()()))(), ((()(()())))(), (()((()))())(), (()((()())))(), ((()()()()))(), ((((()()))))(), (()()()()())(), (((()())()))(), ((())()()())(), (()(()())())(), ((()(())()))(), (()(()(())))(), ((((())))())(), ((((())())))(), ((()())(()))(), (()(((()))))(), ((()((()))))(), ((())(())())(), ((())((())))(), (()(())(()))(), (()()(())())(), (()()((())))(), (((()))()())(), (((())()()))(), (((((())))))(), (((()()())))(), ((()()())())(), ((()()(())))(), (()((())()))(), ((())()(()))(), (((()()))())(), (((())())())(), (()()()(()))(), (((())(())))(), ((())(()()))(), ((()())()())()]
     * <p>
     * 缺少"(()())(()())"
     *
     * @param n
     * @return
     */
    public List<String> generateParenthesisWrong2(int n) 
        List<String> list1 = new ArrayList<>();
        list1.add("()");
        if (n == 1) 
            return list1;
        

        //n=2 3 4 ...
        for (int i = 2; i <= n; i++) 
            Set<String> set = new HashSet<>();
            for (int j = 0; j < list1.size(); j++) 
                String s1 = list1.get(j);
                set.add("()" + s1);//左
                set.add(s1 + "()");//右
                set.add("(" + s1 + ")");//外
                if (s1.charAt(0) == '(' && s1.charAt(s1.length() - 1) == ')') 
                    set.add("(" + s1 + ")");//外
                
                for (int k = 0; k < s1.length() - 1; k++) 
                    if (s1.charAt(k) == '(' && s1.charAt(k + 1) == ')') 
                        set.add(s1.substring(0, k + 1) + "()" + s1.substring(k + 1));//内部
                    
                
            
            list1 = new ArrayList<>(set);
        
        return list1;
    


    public static void main(String[] args) 

        Leetcode_22_Generate_Parentheses main = new Leetcode_22_Generate_Parentheses();
        //System.out.println(main.generateParenthesis(3));
        System.out.println(main.generateParenthesisSolution(3));

    


    /**
     * 方法2:Approach 2: Backtracking
     * Runtime: 2 ms, faster than 65.13% of Java online submissions for Generate Parentheses.
     * Memory Usage: 43.1 MB, less than 78.53% of Java online submissions for Generate Parentheses.
     *
     * @param n
     * @return
     */
    public List<String> generateParenthesisSolution(int n) 
        List<String> ans = new ArrayList();
        backtrack(ans, new StringBuilder(), 0, 0, n);
        return ans;
    

    public void backtrack(List<String> ans, StringBuilder cur, int open, int close, int max) 
        if (cur.length() == max * 2) 
            ans.add(cur.toString());
            return;
        

        if (open < max) 
            cur.append("(");
            backtrack(ans, cur, open + 1, close, max);
            cur.deleteCharAt(cur.length() - 1);
        
        if (close < open) 
            cur.append(")");
            backtrack(ans, cur, open, close + 1, max);
            cur.deleteCharAt(cur.length() - 1);
        
    


    /**
     * 方法3:Approach 3: Closure Number
     * Runtime: 7 ms, faster than 16.99% of Java online submissions for Generate Parentheses.
     * Memory Usage: 42.2 MB, less than 91.80% of Java online submissions for Generate Parentheses.
     *
     * @param n
     * @return
     */
    public List<String> generateParenthesisSolution3(int n) 
        List<String> ans = new ArrayList();
        if (n == 0) 
            ans.add("");
         else 
            for (int c = 0; c < n; ++c)
                for (String left : generateParenthesisSolution(c))
                    for (String right : generateParenthesisSolution(n - 1 - c))
                        ans.add("(" + left + ")" + right);
        
        return ans;
    



以上是关于Leetcode 22. Generate Parentheses - 生成指定数量的有效圆括号,比如输入2,输出()()(())的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 22. Generate Parentheses

leetcode22. Generate Parentheses

leetcode 22 -- Generate Parentheses

[leetcode-22-Generate Parentheses]

LeetCode 22. Generate Parentheses

LeetCode 22. Generate Parentheses