第一题 括号生成

题目

动静布局解法

咱们能够将括号的生成看作
一直的在括号对中退出新的括号
这样对于n对括号的生成 咱们便能在n-1对括号中进行操作


参考
https://leetcode-cn.com/probl...
https://leetcode-cn.com/probl...

java版本

递归实现

// 9mspublic List<String> generateParenthesis(int n) {    List<String> res = new LinkedList<>();    if (n == 0) {        res.add("");        return res;    }    for (int i = 0; i < n; i++) {        int j = n - i - 1;        List<String> iRes = generateParenthesis(i);        List<String> jRes = generateParenthesis(j);        for (String s1 : iRes) {            for (String s2 : jRes) {                res.add(s1 + "(" + s2 + ")");            }        }    }    return res;}作者:fan-lu-5链接:https://leetcode-cn.com/problems/generate-parentheses/solution/java-0ms-cong-zhao-gui-lu-dao-xuan-ding-2qm9t/起源:力扣(LeetCode)著作权归作者所有。商业转载请分割作者取得受权,非商业转载请注明出处。

将小于n的计算结果存储起来供后续计算应用,缩小反复计算

// 8mspublic List<String> generateParenthesis(int n) {    Map<Integer, List<String>> mem = new HashMap<>();    return dp(n, mem);}private List<String> dp(int n, Map<Integer, List<String>> mem) {    if (mem.containsKey(n))        return mem.get(n);    List<String> res = new LinkedList<>();    if (n == 0) {        res.add("");        return res;    }    for (int i = 0; i < n; i++) {        int j = n - i - 1;        List<String> iRes = dp(i, mem);        List<String> jRes = dp(j, mem);        for (String s1 : iRes) {            for (String s2 : jRes) {                res.add(s1 + "(" + s2 + ")");            }        }    }    mem.put(n, res);    return res;}作者:fan-lu-5链接:https://leetcode-cn.com/problems/generate-parentheses/solution/java-0ms-cong-zhao-gui-lu-dao-xuan-ding-2qm9t/起源:力扣(LeetCode)著作权归作者所有。商业转载请分割作者取得受权,非商业转载请注明出处。

go版本

递归实现

func generateParenthesis(n int) []string {    var res []string    if n == 0 {        res=append(res,"")        return res    }    //i从0到n-1 j从n-1到0    for i := 0; i < n; i++ {        j := n - i - 1        //生成i和j的括号序列        iRes := generateParenthesis(i)        jRes := generateParenthesis(j)        for _,s1:=range iRes {            for _,s2:=range jRes {                res=append(res,s1 + "(" + s2 + ")")                }            }        }    return res}

成果

退出存储

func generateParenthesis(n int) []string {    var mem map[int][]string    //如果没有对mem进行初始化,只进行申明 那么mem默认为nil    //在对mem进行赋值操作时会抛出一个panic异样    mem = make(map[int][]string)    return dp(n, mem)}func dp(n int, mem map[int][]string) []string {    if value, ok := mem[n];ok{        return value    }    var res []string    if n == 0 {        res=append(res,"")        return res    }    for i := 0; i < n; i++ {        j := n - i - 1        iRes := dp(i, mem)        jRes := dp(j, mem)        for _,s1:=range iRes {            for _,s2:=range jRes {                res=append(res,s1 + "(" + s2 + ")")            }        }    }    mem[n]=res    return res}

成果

官解 从暴力到回溯

暴力解法


go版本

func generateParenthesis(n int) []string {    var combinations []string    num := make([]byte, 2*n)    generateAll(&num, 0,&combinations)    return combinations}func generateAll(current *[]byte, pos int, result *[]string) {    if pos == len(*current) {        if valid(*current) {            *result = append(*result, string(*current))        }    } else {        (*current)[pos] = '('        generateAll(current, pos+1, result)        (*current)[pos] = ')'        generateAll(current, pos+1, result)    }}func valid(current []byte) bool {    balance := 0    for _,c := range current {        if c == '(' {            balance++        } else {            balance--        }        if balance < 0 {            return false        }    }    return balance == 0}

func generateParenthesis(n int) []string {    res = []string{}    run([]byte{}, 2 * n)    return res}var res []stringfunc run(cur []byte, n int) {    if n == 0 {        if isValid(cur) {            res = append(res, string(cur))        }        return    }    tpl := []byte{'(', ')'}    for i := 0; i < len(tpl); i++ {        cur = append(cur, tpl[i])        run(cur, n - 1)        cur = cur[:len(cur)-1]    }}func isValid(cur []byte) bool {    var st []byte    for i := 0; i < len(cur); i++ {        if cur[i] == '(' {            st = append(st, cur[i])            continue        }        if len(st) == 0 {            return false        }        st = st[:len(st)-1]    }    return len(st) == 0}作者:dfzhou6链接:https://leetcode-cn.com/problems/generate-parentheses/solution/jian-dan-yi-dong-go-by-dfzhou6-frkl/起源:力扣(LeetCode)著作权归作者所有。商业转载请分割作者取得受权,非商业转载请注明出处。

第二题 全排列

题目

递归

每次在nums中挑出一个数作为第一个数,剩下的数进行排列之后放在第一个数前面

剩下的数又能够调用该函数持续实现全排列

反复n次,就实现了所有可能性的组合

代码

func permute(nums []int) [][]int {    var res [][]int    if len(nums) == 0 {        return res    }    var n []int    if len(nums) == 1 {        n = append(n, nums[0])        res = append(res, n)    }    for i := 0; i < len(nums); i++ {        n = append(n, nums[i])        co :=make([]int,len(nums))        copy(co, nums)        co[0], co[i] = co[i], co[0]        pers := permute(co[1:])        for _, per := range pers {            nn := append(n, per...)            res = append(res, nn)        }        n = nil    }    return res}

后果

尽管递归的工夫复杂度比拟快,但在数量级比拟高的时候递归调用栈应用的空间会比拟大

回溯法

https://leetcode-cn.com/probl...

var res [][]intfunc permute(nums []int) [][]int {    res = [][]int{}    backTrack(nums,len(nums),[]int{})    return res}func backTrack(nums []int,numsLen int,path []int)  {    if len(nums)==0{        p:=make([]int,len(path))        copy(p,path)        res = append(res,p)    }    for i:=0;i<numsLen;i++{        cur:=nums[i]        path = append(path,cur)        nums = append(nums[:i],nums[i+1:]...)//间接应用切片        backTrack(nums,len(nums),path)        nums = append(nums[:i],append([]int{cur},nums[i:]...)...)//回溯的时候切片也要还原,元素地位不能变        path = path[:len(path)-1]    }}作者:carlsun-2链接:https://leetcode-cn.com/problems/permutations/solution/dai-ma-sui-xiang-lu-dai-ni-xue-tou-hui-s-mfrp/起源:力扣(LeetCode)著作权归作者所有。商业转载请分割作者取得受权,非商业转载请注明出处。

成果