代码随想录算法训练营第二十四天| 77. 组合

86 阅读1分钟

77. 组合

题目链接

leetcode.cn/problems/co…

文章链接

programmercarl.com/0077.%E7%BB…

视频链接

www.bilibili.com/video/BV1ti…

剪枝操作:

www.bilibili.com/video/BV1wi…

看到题目的第一想法

我看到这道题目的第一想法就是用for循环嵌套,用暴力的方法去解这道题,但是我很快就发现这道题用暴力的方法没有用,因为组合数是k,k是一个变量,k为2,有两层for循环,k为3,有三层for循环。如果我们用暴力去做,则没法控制循环层数,然后我就不知道该怎么去做了。

看完代码随想录之后的想法

看完了才知道用回溯来做这道题,用递归的次数来控制循环的层数,下面附上我的go语言代码:

var result [][]int
func combine(n int, k int) [][]int {
    result = [][]int{}
    backTracking(n, k, 1, []int{})
    return result
}

func backTracking(n, k, startIndex int, track []int) {
    if len(track) == k {
        temp := make([]int, k)
        copy(temp, track)
        result = append(result, temp)
    }
    for i := startIndex; i <= n; i++ {
        track = append(track, i)
        backTracking(n, k, i+1, track)
        track = track[:len(track)-1]
    }
}

这里在for循环里就有回溯的过程了,好不容易append进去的元素,在递归过后又弹出来了,回溯在这里体现了出来。上面的代码还可以进行优化,称之为剪枝,剪枝过后的代码为:

var res [][]int 
func combine(n int, k int) [][]int {
   res=[][]int{}
   if n <= 0 || k <= 0 || k > n {
		return res
	}
    backtrack(n, k, 1, []int{})
	return res
}
func backtrack(n,k,start int,track []int){
    if len(track)==k{
        temp:=make([]int,k)
        copy(temp,track)
        res=append(res,temp)
    }
    if len(track)+n-start+1 < k {
	return
    }
    for i:=start;i<=n;i++{
        track=append(track,i)
        backtrack(n,k,i+1,track)
        track=track[:len(track)-1]
    }
}

实现过程中遇到的困难

困难就是代码不熟悉,回溯算法理解起来有难度,希望以后能更加熟练。

今日收获

知道了排列组合是用回溯来实现的。