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);
}
}
}