力扣---括号生成---回溯---dfs/二进制

本文介绍了如何使用暴力回溯(DFS)算法,结合二进制表示法,递归地生成n对括号的所有可能组合,分别给出了C++和Python的实现,并优化了对左括号数量和右括号数量的判断。

暴力--二进制

采用与:力扣---子集---回溯(子集型回溯)---递归-CSDN博客 中二进制求解一样的思路,即遍历0~2^{2\cdot n}-1(从二进制去考虑),如果这个数的第 i 位为0,则括号的第 i 位为‘( ’,为1代表‘ )’。依次求出所有括号的可能性(总共2^{2\cdot n}种可能),再对每种情况进行判别。

代码:

C++:
class Solution {
public:
    bool check(string temp,int n){
        stack<char> s;
        int num=2*n;
        for(int i=0;i<num;i++){
            //先判断是否配对
            if(temp[i]=='('){s.push(temp[i]);}
            else{
                if(s.empty()){return false;}
                else{s.pop();}
            }
        }
        if(s.empty()){return true;}
        else{return false;}
    }

    vector<string> generateParenthesis(int n) {
        vector<string> res;
        int temp=2*n;
        for(int i=0;i<(1<<temp);i++){ //0代表(,1代表)
            string s;
            for(int j=0;j<temp;j++){
                if(i & (1<<j)){
                    s+=')';
                }
                else{s+='(';}
            }
            //cout<<s<<endl;
            if(check(s,n)){res.push_back(s);}
        }
        return res;
    }
};
Python:
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        
        def check(temp:str,n:int) -> bool:
            s=deque()
            num=2*n
            for i in range(num):
                if temp[i]=='(':
                    s.append(temp[i])
                else:
                    if len(s)==0:
                        return False
                    else:
                        s.pop()
            if len(s)==0:
                return True
            else:
                return False

        
        res=[]
        temp=2*n
        temp_=1<<temp
        for i in range(temp_):
            s=""
            for j in range(temp):
                if i & (1<<j):
                    s+=')'
                else:
                    s+='('
            if check(s,n):
                res.append(s)
        return res

注意:len(s)用于查看队列/栈中元素的个数,string在Python中的写法为str,Python中栈和队列都可以用deque来实现。deque:from collections import deque 

暴力--回溯dfs

采用与:力扣---子集---回溯(子集型回溯)---递归-CSDN博客 中递归法一样的思路,分为三个步骤,第一步骤为特殊情况的判别,即2\cdot n个位置已经填满,对其进行判别。第二步骤为第 i 为设置为‘(’,进行递归调用(注意保护现场)。第三步骤为第 i 为设置为‘ )’,进行递归调用(注意保护现场)。

代码:

C++:
class Solution {
public:
    bool check(string temp,int n){
        stack<char> s;
        int num=2*n;
        for(int i=0;i<num;i++){
            //先判断是否配对
            if(temp[i]=='('){s.push(temp[i]);}
            else{
                if(s.empty()){return false;}
                else{s.pop();}
            }
        }
        if(s.empty()){return true;}
        else{return false;}
    }

    void dfs(int i,vector<string>& res,string temp,int n){
        if(i==2*n){
            if(check(temp,n)){
                res.push_back(temp);
            }
            return;
        }

        //将'('加入temp
        temp+='(';
        dfs(i+1,res,temp,n);
        temp.pop_back();

        //将')'加入temp
        temp+=')';
        dfs(i+1,res,temp,n);
        temp.pop_back();
    }

    vector<string> generateParenthesis(int n) {
        vector<string> res;
        string temp;
        dfs(0,res,temp,n);
        return res;
    }
};
Python:

 

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        
        def check(temp:str,n:int) -> bool:
            s=deque()
            num=2*n
            for i in range(num):
                if temp[i]=='(':
                    s.append(temp[i])
                else:
                    if len(s)==0:
                        return False
                    else:
                        s.pop()
            if len(s)==0:
                return True
            else:
                return False

        
        def dfs(i:int,res:List[str],temp:str,n:int):
            if i==2*n:
                if check(temp,n):
                    res.append(temp)
                return
            temp+='('
            dfs(i+1,res,temp,n)
            temp=temp[0:len(temp)-1]
            temp+=')'
            dfs(i+1,res,temp,n)
            temp=temp[0:len(temp)-1]

        res=[]
        temp=""
        dfs(0,res,temp,n)
        return res
            

对第二种写法的优化:

 我们需要认识到一个点,遍历到第 i 位(即要确定第 i 位是左括号还是右括号时),前 i-1 位的左括号数量一定大于右括号的数量,第 i 位才可能是‘ )’。所以我们可以在这部分进行改进:

//将')'加入temp
temp+=')';
dfs(i+1,res,temp,n);
temp.pop_back();

同时,对特殊情况的判断也可以变为对左括号数量和对右括号数量的判断。

代码:

C++:
class Solution {
public:
    //左括号数>右括号数,才能加右括号
    void dfs(int i,vector<string>& res,string temp,int n,int left,int right){
        if(i==2*n){
            if(left==right){
                res.push_back(temp);
            }
            return;
        }

        //将'('加入temp
        temp+='(';
        dfs(i+1,res,temp,n,left+1,right);
        temp.pop_back();

        //将')'加入temp
        if(left>right){
            temp+=')';
            dfs(i+1,res,temp,n,left,right+1);
            temp.pop_back();
        }
    }

    vector<string> generateParenthesis(int n) {
        vector<string> res;
        string temp;
        dfs(0,res,temp,n,0,0);
        return res;
    }
};
Python:
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:

        def dfs(i:int,res:List[str],temp:str,n:int,left:int,right:int):
            if i==2*n:
                if left==right:
                    res.append(temp)
                return
            temp+='('
            dfs(i+1,res,temp,n,left+1,right)
            temp=temp[0:len(temp)-1]
            if left>right:
                temp+=')'
                dfs(i+1,res,temp,n,left,right+1)
                temp=temp[0:len(temp)-1]
            

        res=[]
        temp=""
        dfs(0,res,temp,n,0,0)
        return res
            

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值