回溯算法解题套路框架-Go语言
解决一个回溯问题实际上就是一个决策树的遍历过程。
- 路径:已经做出的选择
- 选择列表:当前可以做的选择
- 结束条件:达到决策树底层
var result = {}
func backtrack(路径,选择列表) {
if 满足结束条件 {
result.add()
return
}
for 选择 in 选择列表 {
做选择
backtrack(路径,选择列表)
撤销选择
}
}
核心就是for循环里的递归,在递归调用前“做选择”,在递归调用后“撤回选择”。
Go语言解题模板
func permute(nums []type) [][]type {
ans := [][]type{}
temp := []type{}
n := len(nums)
var backTrack func(tmp []type) // 回溯函数声明
backTrack = func(tmp []type) {
if len(tmp) == n { // 递归出口
tmpcp := make([]type, n)
copy(tmpcp, tmp)
ans = append(ans, tmpcp)
// ans = append(ans,append([]int(nil),temp...))
}
for i := 0; i < n; i++ {
// 条件筛选
temp = append(temp, nums[i])
backTrack(temp)
temp = temp[0 : len(temp)-1]
}
}
backTrack(temp)
return ans
}
全排列问题
以[1,2,3]为例,根据常识我们可以画出回溯决策树:

代码实现
返回二维数组
package main
import "fmt"
// 全排列
func permute(nums []int) [][]int {
n := len(nums)
ans := [][]int{}
temp := []int{}
var backTrack func(selected []int)
var contain = func(arr []int, x int) bool {
for i := 0; i < len(arr); i++ {
if x == arr[i] {
return true
}
}
return false
}
// 回溯函数
backTrack = func(selected []int) {
if len(selected) == n {
selectedCopy := make([]int, n)
copy(selectedCopy, selected)
ans = append(ans, selectedCopy)
return
}
for i := 0; i < n; i++ {
if contain(selected, nums[i]) {
continue
}
selected = append(selected, nums[i])
backTrack(selected)
selected = selected[0 : len(selected)-1]
}
}
backTrack(temp)
return ans
}
func main() {
nums := []int{1, 2, 3, 4}
ans := permute(nums)
fmt.Println("最终结果:", ans)
}
/*
最终结果: [[1 2 3 4] [1 2 4 3] [1 3 2 4] [1 3 4 2] [1 4 2 3] [1 4 3 2] [2 1 3 4] [2 1 4 3] [2 3 1 4] [2 3 4 1] [2 4 1 3] [2 4 3 1] [3 1 2 4] [3 1 4 2] [3 2 1 4] [3 2 4 1] [3 4 1 2] [3 4 2 1] [4 1 2 3] [4 1 3 2] [4 2 1 3] [4 2 3 1] [4 3 1 2] [4 3 2 1]]
*/
之所以没有直接ans = append(ans, selected)是这里本人尝试了4个元素的全排列时发现了bug。所以在Go语言里建议copy拷贝后append。
直接输出全排列
package main
import "fmt"
func permute(nums []int) {
n := len(nums)
temp := []int{}
var backTrack func(selected []int)
var contain = func(arr []int, x int) bool {
for i := 0; i < len(arr); i++ {
if x == arr[i] {
return true
}
}
return false
}
backTrack = func(selected []int) {
if len(selected) == n {
fmt.Println(selected)
return
}
for i := 0; i < n; i++ {
if contain(selected, nums[i]) {
continue
}
selected = append(selected, nums[i])
backTrack(selected)
selected = selected[0 : len(selected)-1]
}
}
backTrack(temp)
}
func main() {
nums := []int{1, 2, 3, 4}
permute(nums)
}
/*
[1 2 3 4]
[1 2 4 3]
[1 3 2 4]
[1 3 4 2]
[1 4 2 3]
[1 4 3 2]
[2 1 3 4]
[2 1 4 3]
[2 3 1 4]
[2 3 4 1]
[2 4 1 3]
[2 4 3 1]
[3 1 2 4]
[3 1 4 2]
[3 2 1 4]
[3 2 4 1]
[3 4 1 2]
[3 4 2 1]
[4 1 2 3]
[4 1 3 2]
[4 2 1 3]
[4 2 3 1]
[4 3 1 2]
[4 3 2 1]
*/

浙公网安备 33010602011771号