回溯-排列
跟组合类似,排列也是穷举所有可行解,区别在于排列是有序的,同一个组合可以有多种排列。
比如对组合来说[1,2,3]和[3,2,1]是同一个,但对于排列而言,就是两个。
案例1:给定一个不含重复数字的数组 nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
1.如何避免排列中的重复元素
排列是不可以使用重复元素的,我们可以定义一个used数组来记录以及加入到排列的元素。
2.如何算一个可行解
我们定义n为nums的元素个数,那么当我们的path也有n个元素时,就是一个可行解
class Solution { private List<List<Integer>> lists = new ArrayList<>(); public List<List<Integer>> permute(int[] nums) { //数组长度 int n = nums.length; //阶段性成果 List<Integer> list = new ArrayList<>(n); //状态数组 boolean[] used = new boolean[n]; //排列中数的个数 int count = 0; //开始深度优先搜索 backtrace(list, used, count, nums); return lists; } public void backtrace(List<Integer> list, boolean[] used, int count, int[] nums) { if (count == nums.length) { lists.add(new ArrayList<>(list)); return; } for (int i = 0; i < used.length; i++) { if (!used[i]) { list.add(nums[i]); used[i] = true; backtrace(list, used, count + 1, nums); list.remove(list.size() - 1); used[i] = false; } } } }
案例2:
给定一个可包含重复数字的序列 nums
,按任意顺序 返回所有不重复的全排列。
这个题目是上一个题目的进阶版,序列中有重复元素,但是排列又不能有重复
1.如何保证排列不重复
保证不重复的办法是在合适的地方进行剪枝,首先我们先要对数组进行排序,把相同的元素放在一起。
2.什么时候进行剪枝
在同一层的遍历时,发现自己和前一个元素相同的时候,如果发现前一个元素还未使用,那么这个地方下去一定会重复。
所有这个时候需要进行剪枝操作!
class Solution { List<List<Integer>> res = new ArrayList<>(); /** * * @param nums * @return */ public List<List<Integer>> permuteUnique(int[] nums) { Arrays.sort(nums); List<Integer> path = new ArrayList<>(); int len = nums.length; boolean[] used = new boolean[len]; dfs(nums, path, 0, used); return res; } /** * @param nums * @param path * @param count * @param used */ private void dfs(int[] nums, List<Integer> path, int count, boolean[] used) { int len = nums.length; if (count == len) { res.add(new ArrayList<>(path)); return; } for (int i = 0; i < len; i++) { if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) { continue; } path.add(nums[i]); used[i] = true; dfs(nums, path, count + 1, used); path.remove(path.size() - 1); used[i] = false; } } }
在拓展一下,如果想在三个数中任选两个进行全排列,应该怎么做?
class Solution { private List<List<Integer>> lists = new ArrayList<>(); public List<List<Integer>> permute2(int[] nums,int limit ) { //数组长度 int n = nums.length; //阶段性成果 List<Integer> list = new ArrayList<>(n); //状态数组 boolean[] used = new boolean[n]; //排列中数的个数 int count = 0; //开始深度优先搜索 backtrace2(list, used, count, nums,limit); return lists; } public void backtrace2(List<Integer> list, boolean[] used, int count, int[] nums,int limit ) { if (count == limit) { lists.add(new ArrayList<>(list)); return; } for (int i = 0; i < used.length; i++) { if (!used[i]) { list.add(nums[i]); used[i] = true; backtrace2(list, used, count + 1, nums,limit); list.remove(list.size() - 1); used[i] = false; } } } public static void main(String[] args) { Solution solution = new Solution(); List<List<Integer>> permute = solution.permute2(new int[]{1, 2, 3},2); for (List<Integer> integers : permute) { System.out.println(integers); } } }
输出:
[1, 2] [1, 3] [2, 1] [2, 3] [3, 1] [3, 2]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2021-11-01 python解决线性规划问题
2021-11-01 python解决多变量最优化问题
2021-11-01 python处理单变量优化
2021-11-01 java枚举类常用方法