022 括号生成

LeetCode 第二十二题 括号生成

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

方法一

使用暴力的方法,将所有的括号组合都列举出来,再判断是否符合括号生成的规则。
这里我们使用了一个递归函数,函数首先判断当前生成括号长度是否达到n*2,如果长度满足要求,判断其是否符合括号生成规则,如果符合,将其加入,否则舍弃
如果长度没有达到n*2,添加‘(’和‘)’,递归代码。
在判断其是否符合括号生成规则时,使用一个balance因子,如果是‘(’,balanle自增,如果是‘)’,balance自减,需要注意的是,balance如果小于零,直接返回false,这是因为避免了防止类似于“)(”这种情况

Java

    public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<>();
        generateAll(new char[n * 2], 0, result);
        return result;
    }

    public void generateAll(char[] current, int pos, List<String> result) {
        if (pos == current.length) {
            if (valid(current)) {
                result.add(new String(current));
            }
        } else {
            current[pos] = '(';
            generateAll(current, pos + 1, result);
            current[pos] = ')';
            generateAll(current, pos + 1, result);
        }
    }

    public boolean valid(char[] current) {
        int balance = 0;
        for (char c : current) {
            if (c == '(') {
                balance++;
            } else {
                balance--;
            }
            if (balance < 0)
                return false;/// 防止类似于“)(”这种情况
        }
        return (balance == 0);
    }

C++

小问题

在将Java代码转换到C++过程中,遇到了这样一个问题:char current[]字符串数组在Java中可以直接求出其长度,而在c++中,我们只能使用sizeof()函数或者strlen()函数求其长度。
sizeof()可以求其长度,但当我们将char current[]传入到void generateAll(char current[],int pos,vector<string>& result)时,此时的current就变成一个指针了,使用sizeof()得到的长度始终为4。
strlen()求其长度,strlen()得到的是从第一个字符到’\0’直接的长度,如果字符串中本来就有’\0’,那么我们得到的长度就是错误。

解决办法

使用strlen()求其长度,在char current[]初始化时,为其添加一些字符,如下所示:

for(int i=0; i<n*2; i++)
  current[i]='*';
  current[n*2]='\0';

这样以来,成功的解决了问题,当然,如果你有更好的方法,也可以互相交流。
下面是C++完整代码。

class Solution
{
public:
    vector<string> generateParenthesis(int n)
    {
        vector<string> result = vector<string>();
        char current[n*2+1];
        for(int i=0; i<n*2; i++)
            current[i]='*';
        current[n*2]='\0';
        generateAll(current,0,result);
        return result;
    }
    void generateAll(char current[],int pos,vector<string>& result)
    {
        if(strlen(current)==pos)
        {
            if(valid(current))
            {
                result.push_back(current);
            }
        }
        else
        {
            current[pos]='(';
            generateAll(current,pos+1,result);
            current[pos]=')';
            generateAll(current,pos+1,result);
        }
    }
    bool valid(char current[])
    {
        int balance=0;
        for(int i=0; i<strlen(current); i++)
        {
            if(current[i]=='(')
                balance++;
            else
                balance--;
            if(balance<0)
                return false;
        }
        return (balance==0);
    }
};

Python

在python代码中,遇到了这样的问题:最终输出的结果,result中的结果都是一样的,正如下面代码所展示的一样,输出结果为:[[")",")",")",")",")",")"],[")",")",")",")",")",")"],[")",")",")",")",")",")"],[")",")",")",")",")",")"],[")",")",")",")",")",")"]]

class Solution(object):
    def generateParenthesis(self, n):
        result = []
        current = ['0' for i in range(n * 2)]
        self.generateAll(current, 0, result)
        return result

    def generateAll(self, current, pos, result):
        if (len(current) == pos):
            if self.valid(current):
                result.append(current)
                print(result)
        else:
            current[pos] = '('
            self.generateAll(current, pos + 1, result)
            current[pos] = ')'
            self.generateAll(current, pos + 1, result)

    def valid(self, current):
        balance = 0
        for c in current:
            if (c == '('):
                balance = balance + 1
            else:
                balance = balance - 1
            if (balance < 0):
                return False
        return balance == 0

最终,只好再更改代码,在函数中多传入一个长度参数,成功的解决了问题,代码如下所示:

class Solution(object):
    def generateParenthesis(self, n):
        result = []
        self.generateAll("", n, 0, result)
        return result

    def generateAll(self, current, n, pos, result):
        if (n*2 == pos):
            if self.valid(current):
                result.append(current)
        else:
            current_1 = current + '('
            self.generateAll(current_1, n, pos + 1, result)
            current_2 = current + ')'
            self.generateAll(current_2, n, pos + 1, result)

    def valid(self, current):
        balance = 0
        for c in current:
            if (c == '('):
                balance = balance + 1
            else:
                balance = balance - 1
            if (balance < 0):
                return False
        return balance == 0

方法二

因为符合条件的括号序列,左括号和有括号都是相等的,并且现有左括号,后有右括号,根据这个特点,我们在遍历过程中,直接根据其特性进行组合。

Java

    public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<>();
        backTrack(result, "", 0, 0, n);
        return result;
    }

    public void backTrack(List<String> result, String current, int open, int close, int n) {
        if (n * 2 == current.length()) {
            result.add(current);
        } else {
            if (open < n)
                backTrack(result, current + '(', open + 1, close, n);
            if (close < open)
                backTrack(result, current + ')', open, close + 1, n);
        }

    }

C++

    vector<string> generateParenthesis(int n)
    {
        vector<string> result=vector<string>();
        backTrack(result,"",0,0,n);
        return result;
    }
    void backTrack(vector<string>& result,string current,int open,int close,int n)
    {
        if(n*2==current.length())
            result.push_back(current);
        else
        {
            if(open<n)
                backTrack(result, current+'(',open+1,close,n);
            if(close<open)
                backTrack(result,current+')',open,close+1,n);
        }
    }

Python

    def generateParenthesis(self, n):
        result = []
        self.backTrack(result, "", 0, 0, n)
        return result

    def backTrack(self, result, current, open, close, n):
        if n * 2 == len(current):
            result.append(current)
        else:
            if open < n:
                self.backTrack(result, current + '(', open + 1, close, n)
            if close < open:
                self.backTrack(result, current + ')', open, close + 1, n)

方法三

方法三更加简单明了,因为整个括号表达式都类似于"(" + left + ")" + right这样的形式,也就是首先一个左括号,后面一个右括号,左括号和右括号之间添加一部分,右括号后面添加一部分,根据这个特点,可以将代码写成如下所示。

Java

public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<>();
        if (n == 0)
            result.add("");
        else
            for (int c = 0; c < n; c++)
                for (String left : generateParenthesis(c))
                    for (String right : generateParenthesis(n - 1 - c))
                        result.add("(" + left + ")" + right);
        return result;
    }

C++

    vector<string> generateParenthesis(int n)
    {
        vector<string>result=vector<string>();
        if(n==0)
            result.push_back("");
        else
            for(int c=0; c<n; c++)
            {
                vector<string> result_left=generateParenthesis(c);
                for(int i=0;i<result_left.size();i++)
                {
                    string left=result_left[i];
                    vector<string>result_right=generateParenthesis(n-1-c);
                    for(int j=0;j<result_right.size();j++)
                    {
                        string right=result_right[j];
                        result.push_back("("+left+")"+right);
                    }
                }
            }
        return result;
    }

python

    def generateParenthesis(self, n):
        result = []
        if n == 0:
            result.append("")
        else:
            for c in range(n):
                for left in self.generateParenthesis(c):
                    for right in self.generateParenthesis(n - 1 - c):
                        result.append("(" + left + ")" + right)
        return result

猜你喜欢

转载自blog.csdn.net/liutaotaotaotaotao/article/details/79929987
022