回溯算法解题套路框架-Go语言

解决一个回溯问题实际上就是一个决策树的遍历过程。

  1. 路径:已经做出的选择
  2. 选择列表:当前可以做的选择
  3. 结束条件:达到决策树底层
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]为例,根据常识我们可以画出回溯决策树:

image-20220426182235886

代码实现

返回二维数组

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]
*/
posted @ 2022-06-12 15:42  RedJACK~  阅读(35)  评论(0)    收藏  举报