回溯算法总结

137 阅读1分钟

回溯题集

题一:括号生成

图片.png

思路:DFS遍历,在匹配的过程中,剩余未使用右括号数一定比剩余的左括号数多(等于也行),只要满足这个条件,就一定保证不会出现无效的匹配

代码:

import java.util.ArrayList;
import java.util.List;

public class Solution {

    
    
    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        
        if (n == 0) {
            return res;
        }

        
        dfs("", n, n, res);
        return res;
    }

    
    private void dfs(String curStr, int left, int right, List<String> res) {
        
        if (left == 0 && right == 0) {
            res.add(curStr);
            return;
        }

         
        if (left > right) {
            return;
        }

        if (left > 0) {
            dfs(curStr + "(", left - 1, right, res);
        }

        if (right > 0) {
            dfs(curStr + ")", left, right - 1, res);
        }
    }
}

题二:组合总数

图片.png

思路 深度优先遍历,注意向右深入的时候,可以再次包含当前位置的元素,即非严格向右深入。

回溯的逻辑:对于当前位置所有可以选择的元素:(1)选择一个(2)深入(3)撤销上一次的选择,进入下一次循环重新执行(1)

代码:

class Solution {

    List<List<Integer>> res=new LinkedList();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        //如何不重复选取
        //选一半发现接下来选不了怎么办
        Deque<Integer> path=new LinkedList();
        backtrace(candidates,0,target,path);
        return res;
    }
    /*
        left:剩下待匹配
        path:当前路径
        start 出发的位置

    */
    public void backtrace(int[]candidates,int start, int left,Deque<Integer> path){
        //失败的递归出口
        if(left<0)return;
        //成功的递归出口
        if(left==0){
            //匹配成功
            res.add(new LinkedList(path));
            return;
        }
        /*这个for循环表示的含义:
        1.当前位置可以选的要都选一次
        2.从上一轮的位置开始往后选,不能往前选(防止223 与 322这种重复)
        */
        
        for(int i=start;i<candidates.length;i++){
            path.offerLast(candidates[i]);
            //从i开始回溯,做到可以重复使用candidates[i]
            backtrace(candidates,i,left-candidates[i],path);
            path.pollLast();
        }

    }
}

题三:全排列

图片.png

这是一道排列树的模版题,类似于工作调度,当然了,工作调度可以剪枝。


class Solution {

    List<List<Integer>> list =new ArrayList();

    public List<List<Integer>> permute(int[] nums) {
        dfs(nums,0);
        return list;

    }



    private void dfs(int[] nums,int depth){

    if(depth==nums.length-1){
        //数组怎么转为list存下来
        // ArrayList<Integer> temp=new ArrayList<Integer>(Arrays.asList(nums));
        List<Integer> intList= Arrays.stream(nums).boxed().collect(Collectors.toList());
        list.add(intList);

    }else{
        for(int i=depth;i<nums.length;i++){
            swap(nums,i,depth);
            dfs(nums,depth+1);
            swap(nums,i,depth);
            }
        }
    }




    private void swap(int[]a,int indexl,int indexr){    
        int temp=a[indexl];
        a[indexl]=a[indexr];
        a[indexr]=temp;
    }

}