(leetcode)no.46 全排列(回溯做法)

tech2025-02-27  13

文章目录

题目思路代码结语参考资料


题目

46. 全排列

思路

这里我主要讲的是回溯法的做法。

回溯主要是基于递归的思想,一定要记得,在递归结束后,要撤销选择。在递归之前做出选择,在递归之后撤销刚才的选择,就能正确得到每个节点的选择列表和路径。

大体框架如下:

def backtrack(选择列表,路径): if 满足结束条件: 操作res return for 选择 in 选择列表: if 选择不合法 # 剪枝 continue # 做选择 进入下一层决策树 选择列表.remove(选择) 路径.add(选择) backtrack(选择列表,路径) # 撤销选择 路径.remove(选择)

借用labuladong公众号的一张图来帮助理解一下,这道题的过程大概如下。

代码

import java.util.*; public class Solution { List<List<Integer>> res = new LinkedList<>(); public List<List<Integer>> permute(int[] nums) { if (nums.length == 0) { return res; } // 记录「路径」 LinkedList<Integer> track = new LinkedList<>(); backtrack(nums, track); return res; } // 路径:记录在 track 中 // 选择列表:nums 中不存在于 track 的那些元素 // 结束条件:nums 中的元素全都在 track 中出现 void backtrack(int[] nums, LinkedList<Integer> track) { // 触发结束条件 if (track.size() == nums.length) { // 注意这里要new一个 放入的将会变成引用 res.add(new LinkedList(track)); return; } for(int i=0; i< nums.length; i++){ // 剪去不合法的分支 if(track.contains(nums[i])){ continue; } // 做选择 track.add(nums[i]); // 进入下一层决策树 backtrack(nums, track); // 取消选择 track.removeLast(); } } }

结语

当然就这道题而言,还有很多更优秀的解法,比如dfs、bfs搭配visited等方法剪枝,这些我以后会争取多做些笔记。

比较适用回溯算法的题还有这些,冲冲冲。

39.组合总和

40. 组合总和 II

46. 全排列

47. 全排列 II

78. 子集

90. 子集 II

51. N皇后

参考资料

我的leetcode刷题历程是跟着labuladong大佬混的,没错,就是那个leetcode上一出题解,必属精品的那位。

最新回复(0)