LCR 084. 全排列 II - 力扣(LeetCode)
这道题的主体思想和之前讲过的全排列是相似的,不同的是思考的角度要侧重于剪枝方向,所以可以通过这道题对剪枝思想的进一步扩展;
通过题意,可以知道,在上一层全排列的基础上,增加了重复元素的条件,重复元素的添加,可能会导致重复子序列的出现,例如如下情况:
要避免这种情况,就是要在根源上去剪枝:相同节点的所有分支中,同一个元素只能选择一个,类比于上图,就是在节点 [1,1,2] 中,有两个1,那么只能选择一个。
(还要加上之前的剪枝条件:同一个数只能使用一次)
画决策树,考虑代码实现:
首先要对数组进行优化,让他实现从小到大排序,让重复的元素排列在一起,方便后续的分析;
要让同一节点下,相同的元素只能选择一次,结合下图分析:
所以做出剪枝代码:
代码实现:
class Solution {List<List<Integer>> ret;List<Integer> str;boolean[] check;public List<List<Integer>> permuteUnique(int[] nums) {ret = new ArrayList<>();str = new ArrayList<>();check = new boolean[nums.length];Arrays.sort(nums); // 排序dfs(nums);return ret;}public void dfs(int[] nums){if(str.size() == nums.length){ret.add(new ArrayList(str)); // 递归出口}for(int i=0;i<nums.length;i++){// 剪枝if(check[i] == true || (i!=0 && nums[i]==nums[i-1] && check[i-1]==false)){continue;}str.add(nums[i]);check[i] = true;dfs(nums);// 回溯check[i] = false;str.remove(str.size()-1);}}
}