跟组合类似,排列也是穷举所有可行解,区别在于排列是有序的,同一个组合可以有多种排列。
比如对组合来说[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; } } }
标签:count,排列,nums,int,list,used,回溯,path From: https://www.cnblogs.com/wangbin2188/p/16848870.html