回溯算法之-组合总和请看:https://www.jianshu.com/p/2a9856b96a86
leetcode 46 全排列
给定一个 没有重复数字的序列,返回其所有可能的全排列。
先来说下排列和组合的区别,排列是给定可选择数组中每个数字都需要被使用;而组合则是根据题目要求可选择数组中数字的任意组合,并不是每个数字都需要,也并不是每个数字都需要使用。
还是套用https://www.jianshu.com/p/2a9856b96a86
一文中的回溯算法模板
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
// 排序非必须
Arrays.sort(nums);
// 判断数组中元素是否被使用,这里也可以使用HashSet来判断(因为题干中提示无重复数字)
int[] used = new int[nums.length];
help(res, nums, new ArrayList<Integer>(), used);
return res;
}
private void help(List<List<Integer>> res, int[] nums, ArrayList<Integer> list, int[] used) {
// 当集合元素=数组元素个数时,即代表这是一个全排列
if (list.size() == nums.length) {
res.add(new ArrayList<>(list));
return;
}
for (int i = 0; i < nums.length; i++) {
// 如果该元素已经被使用过了,跳过该元素
if (used[i] == 1) {
continue;
}
// 标识该元素已经被使用
used[i] = 1;
list.add(nums[I]);
help(res, nums, list, used);
// 回溯过后将该元素置为未使用
used[i] = 0;
list.remove(list.size()-1);
}
}
Leetcode 47 全排列2
与46题相比,区别在于给定数字包含重复元素
套模板
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
// 排序非必须
Arrays.sort(nums);
// 判断数组中元素是否被使用,这里也可以使用HashSet来判断(因为题干中提示无重复数字)
int[] used = new int[nums.length];
help(res, nums, new ArrayList<Integer>(), used);
return res;
}
private void help(List<List<Integer>> res, int[] nums, ArrayList<Integer> list, int[] used) {
// 当集合元素=数组元素个数时,即代表这是一个全排列
if (list.size() == nums.length) {
res.add(new ArrayList<>(list));
return;
}
for (int i = 0; i < nums.length; i++) {
// 如果该元素已经被使用过了,跳过该元素
if (used[i] == 1) {
continue;
}
// 这里是与上一题唯一不同的地方,需要进行去重,如果当前数字和前一个数字相等,并且前一个数字是已经回溯过的,则代表他们是树结构的同一层,则进行跳过
if(i>0 && nums[i] == nums[i-1] && (used[i-1]==0)){
continue;
}
// 标识该元素已经被使用
used[i] = 1;
list.add(nums[I]);
help(res, nums, list, used);
// 回溯过后将该元素置为未使用
used[i] = 0;
list.remove(list.size()-1);
}
}