组合、排列辨析
组合:是无序的,例如:[1,2]、[2,1]是同一个;
排列:是有序的,例如:[1,2]、[2,1]是不一样的。
46.全排列
思路
判断结束条件,当小集合满足长度为原数组长度时,结束;因为全排列就是将数组里面的数组按照不同的顺序进行排列,所以长度是不变的;
因为全排列每次都需要从头开始遍历起,所以参数只要有数组就可以,每次从头开始遍历不需要什么索引来限制;
但是每次遍历时候就会出现重复的,所以使用一个int数组used,给已经使用过的值赋值为1,反之为0;所以在遍历过程中当used数组对应遍历位置值为1时,就跳过当前;之后将符合要求的数据加入到小集合中,要记得给used数组对应位置赋值1,之后进行递归,每次都是从头开始的,接下来进行回溯,要记得将used对应位置赋值等于0。
注意
全排列是每次从头开始遍历,使用used数组,当遍历到之前已经加入到集合中的数据时,利用used的标记来跳过;
实现代码
class Solution {
List<List<Integer>> res=new ArrayList<List<Integer>>();
List<Integer> list=new ArrayList<Integer>();
int [] used;
public List<List<Integer>> permute(int[] nums) {
used=new int[nums.length];
backTracking(nums);
return res;
}
public void backTracking(int [] nums){
if(nums.length==list.size()){
res.add(new ArrayList<>(list));
return;
}
for(int i=0;i<nums.length;i++){
if(used[i]==1){
continue;
}
list.add(nums[i]);
used[i]=1;
backTracking(nums);
list.remove(list.size()-1);
used[i]=0;
}
}
}
47.全排列2
思路
基本思想是与全排列一样的,唯一不同的是:此题中的数组是存在重复数据的,那么在按照方法得到全部全排列中会有重复的小集合,所以需要利用“树层去重”将重复的去除。
注意
1.注意一个是树层去重,另外一个是全排列的条件;
2.“树层去重”首先要记得给要排列的数据先进行排序。
实现代码
class Solution {
List<List<Integer>> res=new ArrayList<List<Integer>>();
List<Integer> list=new ArrayList<Integer>();
int [] used;
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);
used=new int[nums.length];
backTracking(nums);
return res;
}
public void backTracking(int [] nums){
if(list.size()==nums.length){
res.add(new ArrayList<Integer>(list));
return;
}
for(int i=0;i<nums.length;i++){
//树层去重
if(i>0&&nums[i-1]==nums[i]&&used[i-1]==0||used[i]==1){
continue;
}
list.add(nums[i]);
used[i]=1;
backTracking(nums);
list.remove(list.size()-1);
used[i]=0;
}
}
}
文章详细阐述了全排列的概念,分别提供了两种全排列的实现:基础全排列和处理重复元素的全排列2。在基础全排列中,通过回溯算法和used数组避免重复。全排列2中,通过对数组排序和树层去重来消除重复的排列。
142

被折叠的 条评论
为什么被折叠?



