22. 括号生成

当前左右括号都有大于 00 个可以使用的时候,才产生分支;
产生左分支的时候,只看当前是否还有左括号可以使用;
产生右分支的时候,还受到左分支的限制,右边剩余可以使用的括号数量一定得在严格大于左边剩余的数量的时候,才可以产生分支;
在左边和右边剩余的括号数都等于 00 的时候结算。

curStr 当前递归得到的结果
     * @param left   左括号还有几个可以使用
     * @param right  右括号还有几个可以使用
     * @param res    结果集

树状分枝,假设走到左或者右

class Solution {

    public List<String> generateParenthesis(int n) {

       //做减法,减枝return

    List<String> res=new ArrayList<>();

     if(n==0)  return null;

     dfs("",n,n,res);

     return res;   

 

    }

 

    private void dfs(String cur,int left,int right,List<String>res){

        if(left==0&&right==0){

          res.add(cur);

          return;

        }

      

    //使用有括号的那条路,然后看left和right

    if(left >right){

         return ;

    }

    if(left>0){

        dfs(cur+"(",left-1,right,res);

    } 

    if(right>0){

        dfs(cur+")",left,right-1,res);

    }

 

    }

}

 

 

主要是跟字符串的特点有关哈,Java 和 Python 里 + 生成了新的字符串,每次往下面传递的时候,都是新字符串。因此在搜索的时候不用回溯。

可以想象搜索遍历的问题其实就像是做实验,每一次实验都用新的实验材料,那么做完了就废弃了。但是如果只使用一份材料,在做完一次以后,一定需要将它恢复成原样(就是这里「回溯」的意思),才可以做下一次尝试。

 StringBuilder 全程只使用一份变量去搜索的做法

 

 

回溯法,减枝
import java.util.ArrayList;
import java.util.List;

public class Solution {

    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        if (n == 0) {
            return res;
        }

        StringBuilder path = new StringBuilder();
        dfs(path, n, n, res);
        return res;
    }


    /**
     * @param path  从根结点到任意结点的路径,全程只使用一份
     * @param left  左括号还有几个可以使用
     * @param right 右括号还有几个可以使用
     * @param res
     */
    private void dfs(StringBuilder path, int left, int right, List<String> res) {
        if (left == 0 && right == 0) {
            // path.toString() 生成了一个新的字符串,相当于做了一次拷贝,这里的做法等同于「力扣」第 46 题、第 39 题
            res.add(path.toString());
            return;
        }

        // 剪枝(如图,左括号可以使用的个数严格大于右括号可以使用的个数,才剪枝,注意这个细节)
        if (left > right) {
            return;
        }

        if (left > 0) {
            path.append("(");
            dfs(path, left - 1, right, res);
            path.deleteCharAt(path.length() - 1);
        }

        if (right > 0) {
            path.append(")");
            dfs(path, left, right - 1, res);
            path.deleteCharAt(path.length() - 1);
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值