LeetCode的几道关于排列的题:
Combination Sum I
public class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>>l=new ArrayList<>();
if(null==candidates)return l;
help(l,new ArrayList<Integer>(),0,target,candidates);
return l;
}//全排列的回溯算法有点和这个类似
public void help(List<List<Integer>>l,List<Integer>t,int index,int target,int[] candidates){
if(target==0){
l.add(new ArrayList<Integer>(t));
return;
}
if(target<0)return;
for(int i=index;i<candidates.length;i++){
t.add(candidates[i]);
//关键就是下面这句索引到底是填index还是填i,关键还是要弄清函数是怎么走的
//填i的话调用的时候会对一个位上的数字重复加,这也是题目需要的,故不能填i+1
//填index的话就是求排列了,会出现和为相同数字的不同排序的case
help(l,t,i,target-candidates[i],candidates);
t.remove(t.size()-1);
}
}
}
Combination Sum II
public class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>>l=new ArrayList<>();
if(candidates==null)return l;
Arrays.sort(candidates);//排序的用处就是用来判断重复的case
help(l,new ArrayList<Integer>(),0,target,candidates);
return l;
}
public void help(List<List<Integer>>l,List<Integer>t,int index,int target,int[] nums){
if(target==0){
l.add(new ArrayList<Integer>(t));
return;
}
if(target<0)return;
for(int i=index;i<nums.length;i++){
//和上面不同的就是简单的判断一个重复case
//下面这句话的意思也就是和另外一个分支有相同的头,因为i!=index故目前就没有在一个分支的头节点,也就是处于index+k如此处的值和前面的有相同的,
//就为重复case,就可以跳过
if(i!=index&&nums[i]==nums[i-1])continue;
t.add(nums[i]);
help(l,t,i+1,target-nums[i],nums);
t.remove(t.size()-1);
}
}
}
Permutation I
public class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>>l=new ArrayList<>();
if(nums==null||nums.length==0){
return l;
}
help(l,0,nums);
return l;
}
public void help(List<List<Integer>>l,int index,int[] nums){
if(index==nums.length){
List<Integer>t=new ArrayList<>();
for(int i:nums)t.add(i);
l.add(t);
return;
}
for(int i=index;i<nums.length;i++){
swap(nums,i,index);
//法1:使用数组拷贝的方法会浪费空间,也就是回到这个函数的状态还是以前的状态,调用其它函数更改的是副本
help(l,index+1,Arrays.copyOf(nums,nums.length));
//法2:会节约空间,每次返回都有此重置的过程
help(l,index+1,nums);
swap(nums,i,index);
}
}
public void swap(int[] nums, int i, int j){
int tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
}
Permutaions II
public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>>l=new ArrayList<>();
Arrays.sort(nums);
if(null==nums||nums.length==0)return l;
help(l,0,nums);
return l;
}
public void help(List<List<Integer>>l, int index,int[] nums){
if(index==nums.length){
List<Integer>t=new ArrayList<>();
for(int i:nums)t.add(i);
l.add(t);
}
for(int i=index;i<nums.length;i++){//和Combination SumII判断重复的思想相似
//由于是和index处的值替换,故判断重复应该与index处的值判断重复
if(i>index&&nums[i]==nums[index])continue;
swap(nums,i,index);
help(l,index+1,Arrays.copyOf(nums,nums.length));
}
}
public void swap(int[] nums, int i,int j){
int tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
}