回溯

回朔算法是使用递归的方式,遍历所有的状态,一般借助数组等结构进行“剪枝”,较少遍历的次数。

解决的是 子集、组合、排列 问题。注意边界条件。
子集和排列和顺序无关,要借助位置信息防止重复;
排列和位置无关,只需判断辅助数据结构(path)中是否包含当前元素

下文介绍这几种的标准代码。

1、子集

力扣78题:给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

class Solution {

    List> res = new ArrayList();
    List path = new ArrayList();

    public List> subsets(int[] nums) {
        dfs(nums, 0);
        return res;
    }

    // 注意index的用法
    public void dfs(int[] nums, int index) {
        res.add(new ArrayList(path));
        for(int i=index;i

2、组合

组合是在子集的基础上进行剪枝,过程中不匹配直接返回,不在继续递归。
力扣77:给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

class Solution {

    List> res = new ArrayList();
    List path = new ArrayList();

    public List> combine(int n, int k) {
        dfs(n, k, 1);
        return res;
    }

    public void dfs(int n, int k, int index) {
        // 剪枝:组合是特定的子集,保留符合的
        if(k == path.size()) {
            res.add(new ArrayList(path));
            return ;
        }
        for(int i=index;i<=n;i++) {
            path.add(i);
            dfs(n, k, i+1);
            path.remove(path.size()-1);
        }
    }
}

3、排列

力扣46题: 全排列 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

class Solution {

    List> res = new ArrayList();
    List path = new ArrayList();

    public List> permute(int[] nums) {
        dfs(nums);
        return res;
    }

    public void dfs(int[] nums) {
        if(path.size() == nums.length) {
            res.add(new ArrayList(path));
            return;
        }
        for(int i=0;i

你可能感兴趣的:(回溯)