回溯组合Leetcode78:

和字母组合差不多的逻辑,但是多了一个k长度的组合,有了这个组合就不能用多重循环了,如果使用多重循环要循环K层,当k很大的时候复杂度就不够了。因此想到另一种暴力的解法回溯。

还是回溯三部曲:

#    1、画图找递归点

图依然有点丑,哈哈

 

图中可以看到,for横向处理的逻辑应该从1到n,为什么是从1到n呢从测试用例可以看到组合的起点应该是1,所以其实索引startIndex应该是等于1的。

#    2、确定递归出口

递归出口时什么呢?很容易能想到当paths的长度达到k的长度就可以可以处理逻辑了。贴上代码:

 

if len(paths) == k {

        temp := make([]int, len(paths))

        copy(temp, paths)

        *res = append(*res, temp)

        return

    }

 

这里有个坑,初始的时候我是声明了一个临时切片temp,让temp=paths了,输出(1,2)、(1,3)会被(1,4)覆盖掉,这是因为slice是引用类型,在回溯过程中,path 会不断地被修改和回溯,赋值给temp会直接影响temp的值。所以应该直接copy创建新得切片。

#    3、处理for循环内的单层逻辑

单层逻辑只需要把i逐层得加到paths就好了,但是递归得时候不应该是startIndex+1了,如果是startIndex+1得话就会造成字符重复使用,所以应该是i+1。后续就是paths滞空回溯就好。贴代码:

for i := startIndex; i <= n; i++ {

        //单层逻辑

        paths = append(paths, i)

        backtracking(n, k, i+1, paths, res)

        paths = paths[:len(paths)-1]

    }

 

最后贴上整段代码:


package main


import "fmt"


func combine(n int, k int) (res [][]int) {


    startIndex := 1

    backtracking(n, k, startIndex, []int{}, &res)

    return

}


func backtracking(n int, k int, startIndex int, paths []int, res *[][]int) {

    if len(paths) == k {

        temp := make([]int, len(paths))

        copy(temp, paths)

        *res = append(*res, temp)

        return

    }

    for i := startIndex; i <= n; i++ {

        //单层逻辑

        paths = append(paths, i)

        backtracking(n, k, i+1, paths, res)

        paths = paths[:len(paths)-1]

    }


}


func main() {

    c := combine(4, 2)

    fmt.Println(c)

}


但是回溯时间复杂度不理想,后续还想能不能用自顶向下得记忆化搜索或者自底向上得动态规划重构一下。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值