LeetCode每日一题,括号生成|刷题打卡

187 阅读1分钟

题目

括号生成

leetcode-cn.com/problems/ge…

公众号 《java编程手记》记录JAVA学习日常,分享学习路上点点滴滴,从入门到放弃,欢迎关注

描述

难度:中等

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

示例 2:

输入:n = 1
输出:["()"]

提示:

1 <= n <= 8

题意解析

更好的理解题意非常有助于解题,所以加入了题意解析环节

这道题本质上是通过输入的数字N,生成N(),并且左括号右括号可打乱排列,但是必须有效,即必须要一一对应,不可以出现)))(((类似这样的例子

那么这道题的第一个思路就出来了,暴力解法,我们只需要按照N的值去生成所有可能生成的括号即可,然后通过出栈入栈操作来筛选符合有效这个规则的结果即可,暴力解法的结果就是时间复杂度很高,生成的括号数为2N(左右括号两个),需要生成2^2N个结果值,对于每个结果最多可能需要N层遍历才可知道结果值是否有效,最终时间复杂度为O(2^2N*N)

由于暴力解法实在累人,就没有去写,直接进入正题,回溯法,简单介绍下回溯法 把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解,说白了就是将思路转换为树的数据结构,然后进行搜索,找到最优解的一种解法,针对这道题,我在leetCode的解法中找到了一张十分形象的图,能够很生动的描述,树状,遍历等行为,废话不多说直接上图

img

Solution

回溯解法

解题思路

img

整体解题思路

  • 设定两个变量leftright用来表示可添加的左括号数可添加的右括号数
  • 当添加一个左括号后,可添加左括号数量减一,即left--,同时当新增一个左括号后,对应需要有一个右括号,即右括号数加一,right++
  • 当添加一个右括号后,可添加左括号数量不变,可添加右括号数减一,right--
  • left>0时,可以选择继续添加左括号,同时left--,right++
  • right>0时,可以选择继续添加右括号,同时right--,left不变
  • leftright都为0时,即没有可添加的左括号和右括号,扔入结果返回

CODE

class Solution {
  	//结果list
    List<String> list = new ArrayList();
    public List<String> generateParenthesis(int n) {
      	//初始left为n,right为0,字符串为空串
        backtrace("",n,0);
        return list;
    }

    public void backtrace(String str,int left , int right){
      	//left和right都为0时,组装结果,返回
        if(left==0 && right==0){
            list.add(str);
            return ;
        }
        //有可用的左括号时,添加左括号,继续递归,同时left-1,right+1
        if(left > 0){
            backtrace(str+"(",left-1,right+1);
        }
        //有可用的右括号时,添加左括号,继续递归,同时left不变,right-1
        if(right > 0){
            backtrace(str+")",left,right-1);
        }
    }
}

复杂度

  • 算不出来哈哈

结果

  • 执行用时:1 ms, 在所有 Java 提交中击败了96.69%的用户
  • 内存消耗:38.7 MB, 在所有 Java 提交中击败了43.76%的用户

LeetCode名句

woshishabi

参考:leetcode-cn.com/problems/ge…