day22任务

主要是回溯算法,对于回溯算法,首先脑子里需要大概的模拟,然后就可以套模板了,个人认为目前比较难的是参数的确认以及适当剪枝。

一、回溯是什么(代码随想录网站):带你学透回溯算法(理论篇)| 回溯法精讲!_哔哩哔哩_bilibili

重点抽象为树形结构,然后就好理解了。

二、回溯算法可以解决什么问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 切割问题:一个字符串按一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 棋盘问题:N皇后,解数独等等

三、模板:回溯三部曲是什么?

以上所有内容均来自代码随想录网站:代码随想录


1.回溯的理论

三部曲怎么走?

回溯法抽象为树形结构后,其遍历过程就是:for循环横向遍历,递归纵向遍历,回溯不断调整结果集

  • 回溯函数模板返回值以及参数

    返回值void
    一般是先写逻辑,然后需要什么参数,就填什么参数
  • 回溯函数终止条件
    if (终止条件) {
        存放结果;
        return;
    }
  • 回溯搜索的遍历过程

    回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。
    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }

 2.组合问题:代码随想录

力扣链接:. - 力扣(LeetCode)

个人理解都在代码注释中(包含剪枝):

/**
 * 组合
 *
 * https://leetcode.cn/problems/combinations/
 */
public class _22_1Combine1 {
    static List<List<Integer>> result = new ArrayList<>();
    static LinkedList<Integer> path = new LinkedList<>();
    public static List<List<Integer>> combine(int n, int k) {
        backTracking(n,k,1);
        return result;
    }

    public static void backTracking(int n,int k,int startIndex){
        if (path.size() == k){
            result.add(new ArrayList<>(path));
            return;
        }

        for (int i = startIndex; i<= n-k+path.size()+1;i++){    //这是剪枝过的回溯
            path.add(i);    //1.注意要添加的元素
            backTracking(n, k, i+1);    //2.回溯
            path.removeLast();  //3.注意不断调整结果集
        }
    }
    public static void main(String[] args) {
        int n =4;
        int k =2;
        System.out.println(combine(n,k));
    }
}

3.组合总和:代码随想录

力扣链接:. - 力扣(LeetCode)

/**
 * 组合总和III
 *
 * https://leetcode.cn/problems/combination-sum-iii/
 */
public class _22_3Combine3 {
    static List<List<Integer>> result = new ArrayList<>();

    static LinkedList<Integer> path = new LinkedList<>();

    public static List<List<Integer>> combinationSum3(int k, int n) {
        backTracking(n, k, 1, 0);  //还是回溯的模板,看看里面的逻辑有什么不同
        return result;
    }

    public static void backTracking(int targetNum, int k, int startIndex, int sum) {
        if (sum > targetNum) {     //1.增加了判断,还是回溯的终止条件
            return;
        }
        if (path.size() == k) {     //控制回溯的深度
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = 1; i < 9 - k + path.size() + 1; i++) {     //还是可以剪枝的
            path.add(i);
            sum += i;     //2.多了个sum+=i的操作,因为要找组合的和
            backTracking(targetNum, k, i + 1, sum);   //还是回溯
            path.removeLast();      //不断调整参数,模板核心没变
            sum -= i;     //调整参数记得同时调整sum
        }
    }
}

4.电话号码的字母组合:代码随想录

力扣链接:. - 力扣(LeetCode)

注意用数组实现数字和字母的映射关系操作

注意numIndex表示的含义

public class _22_4PhoneNumberLetterCombination {
    List<String> result = new ArrayList<>();

    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) {
            return result;
        }
        //初始化数组,对应数字的字符
        String[] numStrings = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
        backTracking(digits, numStrings, 0);
        return result;
    }

    StringBuilder temp = new StringBuilder();   //StringBuilder操作更灵活些

    public void backTracking(String digits, String[] numStrings, int numIndex) {    //numIndex就是当前回溯的深度,用来遍历digits
        if (numIndex == digits.length()) {
            result.add(temp.toString());    //断点1,可以看看怎么执行的
            return;
        }
        String str = numStrings[digits.charAt(numIndex) - '0'];
        for (int i = 0; i < str.length(); i++) {
            temp.append(str.charAt(i));
            //递归,下一层处理
            backTracking(digits, numStrings, numIndex + 1);     //断点2,可以看看怎么执行的
            //尝试别的组合,调整参数
            temp.deleteCharAt(temp.length() - 1);
        }
    }

    public static void main(String[] args) {
        String input = "23";
        _22_4PhoneNumberLetterCombination phoneNumberLetterCombination = new _22_4PhoneNumberLetterCombination();
        System.out.println(phoneNumberLetterCombination.letterCombinations(input));
    }
}

上面几个题都是回溯的模板应用,属于第一级难度,多练习,无他,唯手熟尔(本人菜鸡一枚,脑子还不灵光,只能多记录了),以下截图源于代码随想录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值