给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
思路 + 代码
本题很容易想到要用 深度遍历+回溯剪枝 来进行解答,主要难点在于所给数组中存在相同数字,即如何在回溯过程中就剪枝去重。
首先对数据升序排列,在同一层递归中,如果后面一个数字和前面一个数字一样,且这两个数字都没被使用过,在for循环中,后面这个数字就可以直接跳过,没必要再重复一次dfs。
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList();
List<Integer> path = new ArrayList();
boolean[] used = new boolean[nums.length]; //记录某元素是否已经使用过
dfs(nums,0, nums.length,used, res, path);
return res;
}
public void dfs(int[] nums, int depth, int len, boolean[] used, List<List<Integer>> res, List<Integer> path){
if (depth == len){
// 成功条件
res.add(new ArrayList(path));
return;
}
for (int i = 0; i < len; i++){
if (used[i]) continue; // 已经用了直接过
// 剪枝核心,
if (i > 0 && nums[i] == nums[i-1] && !used[i-1]) continue;
// 递归以及回溯主代码
used[i] = true;
path.add(nums[i]);
dfs(nums, depth + 1, len, used, res, path);
path.remove(path.size()-1);
used[i] = false;
}
}
}
网友评论