46题目: 给定一个没有重复数字的序列,返回其所有可能的全排列。
借鉴了大神关于排列问题的总结和代码。https://blog.csdn.net/Jacky_chenjp/article/details/66477538?utm_source=copy
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路:
在代码中使用了交换前后元素和DFS(深度优先搜索)的思想。DFS就是一直搜索知道到达搜索结构的叶子节点。我是在和图相关的算法中了解到的这种思想,用途还是挺广的。
代码:
public class Solution {
// 最终返回的结果集,作为类变量
List<List<Integer>> res = new ArrayList<List<Integer>>();
public List<List<Integer>> permute(int[] nums) {
int len = nums.length;
if (len==0||nums==null) return res;
// 采用前后元素交换的办法,dfs解题
exchange(nums, 0, len);
return res;
}
public void exchange(int[] nums, int i, int len) {
// 将当前数组加到结果集中 相当于到达DFS的叶子节点
if(i==len-1) {
List<Integer> list = new ArrayList<>();
for (int j=0; j<len; j++){
list.add(nums[j]);
}
res.add(list);
return ;
}
// 将当前位置的数跟后面的数交换,并搜索解
for (int j=i; j<len; j++) {
swap(nums, i, j);
exchange(nums, i+1, len);
swap(nums, i, j);
}
}
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
47题目:
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
思路:与46不同的是可以包含重复数字。首先对数组进行排序,将相同的元素放在一起;其次在执行DFS函数时,对于当前元素与前一个元素相同并且当前元素为被添加到list中(即对应的used[]数组为false)时跳过该元素。
整体是递归的思想。将第一个元素放在list的第一个位置,将used设置为true,然后依次对之后的元素调用dfs,知道list的长度和nums长度相同(找到组合);每处理完以一个元素开头的组合就将其设置为false;对于之后相同的元素,由于前一个元素为false,不在list中,所以跳过该元素。
也可以把所有组合的结果当放入set中去除重复的元素(但可能需要的空间比较大吧)
代码:
public class Solution {
List<List<Integer>> res = new ArrayList<List<Integer>>(); //存放最后结果
public List<List<Integer>> permuteUnique(int[] nums) {
int len = nums.length;
if(len==0||nums==null) return res;
boolean[] used = new boolean[len]; //用来标记元素,跳过相同元素
List<Integer> list = new ArrayList<Integer>(); //用来保存每一种组合结果
Arrays.sort(nums); //将数组从小到大进行排序
dfs(nums, used, list, len);
return res;
}
public void dfs(int[] nums, boolean[] used, List<Integer> list, int len) {
if(list.size()==len) { //将当前组合添加到结果集中
res.add(new ArrayList<Integer>(list));
return ;
}
for (int i=0; i<len; i++) {
// 当前位置的数已经在List中了
if(used[i]) continue;
// 当前元素与其前一个元素值相同 且 前元素未被加到list中,跳过该元素
if(i>0 && nums[i]==nums[i-1] && !used[i-1]) continue;
// 深度优先搜索遍历
used[i]=true;
list.add(nums[i]);
dfs(nums, used, list, len);
list.remove(list.size()-1);
used[i]=false;
}
}
}