回溯问题学习总结

回溯问题

三种情况

每种情况都有子集,组合,排列三种题型

无重复元素不可复选

//子集问题 
static List<List<Integer>> res=new LinkedList<>();
    static LinkedList<Integer> track=new LinkedList<>();
    //无重复元素
    public static List<List<Integer>> subsets(int[] nums) {
        back(nums,0);
        return res;
    }
​
    static void back(int[] nums,int start){
        res.add(new LinkedList<>(track));
        for (int i=start;i<nums.length;i++){
            track.add(nums[i]);
            back(nums,i+1);
            track.removeLast();
        }
    }
​
//组合问题
static List<List<Integer>> res=new LinkedList<>();
    static LinkedList<Integer> track=new LinkedList<>();
    public static List<List<Integer>> combine(int n, int k) {
        backtrack(n,1,k);
        return res;
    }
    static void backtrack(int n,int start,int k){
        if(track.size()==k){
            res.add(new LinkedList<>(track));
        }
        for (int i=start;i<=n;i++){
            track.add(i);
            backtrack(n,i+1,k);
            track.removeLast();
        }
    }
//排列问题
static List<List<Integer>> res=new LinkedList<>();
    static LinkedList<Integer> track=new LinkedList<>();
    public static List<List<Integer>> permute(int[] nums) {
      back(nums,track);
      return res;
    }
​
    static void back(int[] nums,LinkedList<Integer> track){
        if(track.size()== nums.length){
            res.add(new LinkedList<>(track));
            return;
        }
        for (int i=0;i<nums.length;i++){
            if(track.contains(nums[i])) continue;
            track.add(nums[i]);
            back(nums,track);
            track.removeLast();
        }
    }

有重复元素不可复选

//子集问题
List<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> track = new LinkedList<>();
​
public List<List<Integer>> subsetsWithDup(int[] nums) {
    // 先排序,让相同的元素靠在一起
    Arrays.sort(nums);
    backtrack(nums, 0);
    return res;
}
​
void backtrack(int[] nums, int start) {
    // 前序位置,每个节点的值都是一个子集
    res.add(new LinkedList<>(track));
  
    for (int i = start; i < nums.length; i++) {
        // 剪枝逻辑,值相同的相邻树枝,只遍历第一条
        if (i > start && nums[i] == nums[i - 1]) {
            continue;
        }
        track.addLast(nums[i]);
        backtrack(nums, i + 1);
        track.removeLast();
    }
}
//组合问题
List<List<Integer>> res = new LinkedList<>();
​
LinkedList<Integer> track = new LinkedList<>();
​
int trackSum = 0;
​
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    if (candidates.length == 0) {
        return res;
    }
    // 先排序,让相同的元素靠在一起
    Arrays.sort(candidates);
    backtrack(candidates, 0, target);
    return res;
}
​
void backtrack(int[] nums, int start, int target) {
        if (trackSum == target) {
        res.add(new LinkedList<>(track));
        return;
    }
  
    if (trackSum > target) {
        return;
    }
​
   
    for (int i = start; i < nums.length; i++) {
        // 剪枝逻辑,值相同的树枝,只遍历第一条
        if (i > start && nums[i] == nums[i - 1]) {
            continue;
        }
   
        track.add(nums[i]);
        trackSum += nums[i];
  
        backtrack(nums, i + 1, target);
  
        track.removeLast();
        trackSum -= nums[i];
    }
}
//排列问题
List<List<Integer>> res = new LinkedList<>();LinkedList<Integer> track = new LinkedList<>();
boolean[] used;
​
public List<List<Integer>> permuteUnique(int[] nums) {
    // 先排序,让相同的元素靠在一起
    Arrays.sort(nums);
    used = new boolean[nums.length];
    backtrack(nums);
    return res;
}
​
void backtrack(int[] nums) {
    if (track.size() == nums.length) {
        res.add(new LinkedList(track));
        return;
    }
​
    for (int i = 0; i < nums.length; i++) {
        if (used[i]) {
            continue;
        }
        // 新添加的剪枝逻辑,固定相同的元素在排列中的相对位置
        if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
            continue;
        }
        track.add(nums[i]);
        used[i] = true;
        backtrack(nums);
        track.removeLast();
        used[i] = false;
    }
}

无重复元素可复选

​
​
//子集问题
List<List<Integer>> res = new LinkedList<>();
​
LinkedList<Integer> track = new LinkedList<>();
​
int trackSum = 0;
​
public List<List<Integer>> combinationSum(int[] candidates, int target) {
    if (candidates.length == 0) {
        return res;
    }
    backtrack(candidates, 0, target);
    return res;
}
​
​
void backtrack(int[] nums, int start, int target) {
  
    if (trackSum == target) {
        res.add(new LinkedList<>(track));
        return;
    }
   
    if (trackSum > target) {
        return;
    }
​
  
    for (int i = start; i < nums.length; i++) {
   
        trackSum += nums[i];
        track.add(nums[i]);
   
  
        backtrack(nums, i, target);
  
        trackSum -= nums[i];
        track.removeLast();
    }
}
​
//排列问题
List<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> track = new LinkedList<>();
​
public List<List<Integer>> permuteRepeat(int[] nums) {
    backtrack(nums);
    return res;
}
​
​
void backtrack(int[] nums) {
  
    if (track.size() == nums.length) {
  
        res.add(new LinkedList(track));
        return;
    }
​
  
    for (int i = 0; i < nums.length; i++) {
  
        track.add(nums[i]);
    
        backtrack(nums);
      
        track.removeLast();
    }
posted @ 2022-08-23 15:06  山野村夫01  阅读(20)  评论(0编辑  收藏  举报