题目
(46). 全排列
题目描述
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例
示例一
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路
1、路径:也就是已经做出的选择;
2、选择列表:也就是你当前可以做的选择;
3、结束条件:也就是到达决策树底层,无法再做选择的条件。
路径:记录已经做过的选择;
选择列表:表示当前可以做的选择;
结束条件:就是遍历到树的底层,在这里就是选择列表为空的时候。
框架
for 选择 in 选择列表:
# 做选择
将该选择从选择列表移除
路径.add(选择)
backtrack(路径, 选择列表)
# 撤销选择
路径.remove(选择)
将该选择再加入选择列表
代码
// permuteV2
// 全排列
// 回溯问题
// 产生问题
func permuteV2(nums []int) [][]int {
result := [][]int{}
// 是否存在
visited := map[int]bool{}
var backtrack func(path []int)
backtrack = func(path []int) {
// 满足结束条件
if len(path) == len(nums) {
// TODO 直接赋值 与 copy方式赋值结果不一致
// 原因:切片赋值会直接拷贝原数组的地址,如果原数组发生了变化,赋值后的元素也会发生变化
// 使用copy因为需要新创建一个切片,使用了新创建的地址,所以如此问题
// temp := path
// 通过copy方式赋值
temp := make([]int, len(path))
copy(temp, path)
result = append(result, temp)
log.Println("temp", temp, &path, result)
return
}
for _, index := range nums {
// 做选择
if bo, ok := visited[index]; ok && bo {
continue
}
visited[index] = true
path = append(path, index)
backtrack(path)
log.Println(index, path)
// 撤销选择
visited[index] = false
path = path[:len(path)-1]
if len(path) == 0 {
log.Println("一轮结束")
}
}
}
backtrack([]int{})
return result
}
参考
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/pe…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。