491.递增子序列
HashSet 用于记录已经选择过的元素,确保同一层级中不会选择重复的元素。这样可以保证在回溯的过程中,只会选择不同的元素组合,避免产生重复的递增子序列。
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backtrack(nums,0);
return res;
}
void backtrack(int[] nums, int start){
if(path.size() >= 2) res.add(new ArrayList<>(path));
HashSet<Integer> hs = new HashSet<>();
for(int i = start; i < nums.length; i++){
if(!path.isEmpty() && path.get(path.size() -1) > nums[i] || hs.contains(nums[i])) continue;
hs.add(nums[i]);
path.add(nums[i]);
backtrack(nums, i + 1);
path.remove(path.size() - 1);
}
}
}
46.全排列
梦开始的地方,最开始写回溯不会用标记数组,递归只是处理循环层数不确定的问题
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new LinkedList<>();
public List<List<Integer>> permute(int[] nums) {
backtrack(nums,path,0);
return res;
}
void backtrack(int[] nums,List<Integer> path,int start){
if(path.size()==nums.length){
res.add(new ArrayList<>(path));
return;
}
for(int i=start;i<nums.length;i++){
if(!path.contains(nums[i])){
path.add(nums[i]);
backtrack(nums, path,0);
path.removeLast();
}
}
}
}
加上标记数组就是剪枝了·
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new LinkedList<>();
boolean[] used;
public List<List<Integer>> permute(int[] nums) {
if (nums.length == 0) return res;
used = new boolean[nums.length];
backtrack(nums);
return res;
}
void backtrack(int[] nums){
if (path.size() == nums.length){
res.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < nums.length; i++){
if (used[i]) continue;
used[i] = true;
path.add(nums[i]);
backtrack(nums);
path.removeLast();
used[i] = false;
}
}
}
47.全排列 II
跟上一题相比,在每次循环中,如果当前元素与前一个元素相同且前一个元素未被使用过,则跳过当前元素,以避免生成重复的排列。
class Solution {
List<List<Integer>> res = new LinkedList<>();
List<Integer> path = new LinkedList<>();
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
used = new boolean[nums.length];
Arrays.sort(nums);
backtrack(nums, 0);
return res;
}
void backtrack(int[] nums,int start){
if(nums.length==path.size()) res.add(new LinkedList<>(path));
for(int i=0;i<nums.length;i++){
if(i>0&&nums[i]==nums[i-1]&&!used[i-1]) continue;
if(!used[i]){
path.add(nums[i]);
used[i] = true;
backtrack(nums, i+1);
path.removeLast();
used[i] = false;
}
}
}
}