题目的链接在这里:https://leetcode-cn.com/problems/permutations-ii/
题目大意
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。一、示意图
二、解题思路
Set暴力
代码如下:
class Solution {
//第一种方法就是 直接用dfs全排列 然后用set暴力去重
Set<List<Integer>> set=new HashSet<>();
public List<List<Integer>> permuteUnique(int[] nums) {
//然后直接调用dfs 再使用set去重
dfs(nums,0);
List<List<Integer>> result = new ArrayList<>(set);
return result;
}
private void dfs(int[] nums, int i) {
//dfs的遍历 先写结束条件吧
if(i==nums.length){
//把最后一个都遍历到了 需要把数据放到set里面了
List<Integer> line=new ArrayList<>();
for(int k:nums){
line.add(k);
}
//再把line也放进去
set.add(line);
}
//如果没有到结束的时候
else{
//那就开始 从当前出发i出发 这个遍历规则 从何而来呢
for(int j=i;j<nums.length;j++){
//这个时候k和i相等 也要swap吗
swap(nums,i,j);
//可能是因为这一步的存在 让i+1的dfs时,nums可以保持原状
dfs(nums,i+1);
//这里还有细节会回溯回来
swap(nums,i,j);
}
}
}
private void swap(int[] nums, int k, int i) {
int temp=nums[k];
nums[k]=nums[i];
nums[i]=temp;
}
}
DFS判断
代码如下:
class Solution {
//第二种方法就是 dsf全排列搜索前,先判断是否交换过、
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
//然后直接调用dfs 再使用set去重
dfs(nums,0);
return result;
}
private void dfs(int[] nums, int i) {
//dfs的遍历 先写结束条件吧
if(i==nums.length){
//把最后一个都遍历到了 需要把数据放到set里面了
List<Integer> line=new ArrayList<>();
for(int k:nums){
line.add(k);
}
//再把line也放进去 这里就直接加进去
result.add(line);
}
//如果没有到结束的时候
else{
//那就开始 从当前出发i出发 这个遍历规则 从何而来呢
//这个的排序思路就是 把一个数值 在每一个位置都进行遍历
//但是为什么需要是从i开始而不是i+1 而且i+1输出出来的时候 一个空的
for(int k=i;k<nums.length;k++) {
//这个时候k和i相等 也要swap吗
if (canSwap(nums, i, k)) {
swap(nums, k, i);
//可能是因为这一步的存在 让i+1的dfs时,nums可以保持原状
dfs(nums, i + 1);
swap(nums, k, i);
}
}
}
}
//这个方法就是用来判断 这两个位置是否能进行交换
private boolean canSwap(int[] nums, int i, int k) {
//也想想看 怎么样才算这两个位置不能交换呢 直接判断 从k到i 之间存在等于i的值 这样就算是 之前已经交换过了
for(int j=i;j<k;j++){
//如果出现相等的 就不需要交换了
if(nums[k]==nums[j])
return false;
}
//否则就是默认可以
return true;
}
private void swap(int[] nums, int k, int i) {
int temp=nums[k];
nums[k]=nums[i];
nums[i]=temp;
}
}