回溯算法 | part01

回溯算法是一个纯暴力搜索的算法,适用于组合,切割,子集,排列,棋盘问题,理解回溯算法,可以将其转化为树的结构进行理解,n叉树

77. 组合 - 力扣(LeetCode)

给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]

复制代码
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();

public List<List<Integer>> combine(int n, int k) {
    //组合问题
    backtracking(n, k, 1);
    return res;
}

public void backtracking(int n, int k, int startIndex){
    //确认终止条件,到达叶子节点说明找到一种结果
    if (path.size() == k){
        //添加结果
        res.add(new ArrayList<>(path));
        return;
    }
    //确定单层递归逻辑,从startIndex开始遍历,遍历剩余元素
    for (int i = startIndex; i <= n; i++) {
        path.add(i);
        //递归
        backtracking(n, k, i + 1);
        //回溯
        path.remove(path.size() - 1);
    }
}

优化:剪枝操作

如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了

复制代码
for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置

216. 组合总和 III - 力扣(LeetCode)

找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。

说明:

  • 所有数字都是正整数。
  • 解集不能包含重复的组合。

示例 1: 输入: k = 3, n = 7 输出: [[1,2,4]]

示例 2: 输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]]

复制代码
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
int sum = 0;

public List<List<Integer>> combinationSum3(int k, int n) {
    backtracking(n, k, 1);
    return res;
}

public void backtracking(int n, int k, int startIndex){
    if (path.size() == k && sum == n){
        res.add(new ArrayList<>(path));
        return;
    }
    //剪枝
    if (sum > n){
        return;
    }
    for (int i = startIndex; i <= 9; i++) {
        path.add(i);
        sum += i;
        backtracking(n, k, i + 1);
        sum -= i;
        path.remove(path.size() - 1);
    }
}

解题:

就是在前面那一题的基础上统计和。进一步剪枝:

for (int i = startIndex; i <= 9 - (k - path.size()) + 1 ; i++)

17. 电话号码的字母组合 - 力扣(LeetCode)

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例:

  • 输入:"23"
  • 输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

说明:尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

复制代码
List<String> res = new ArrayList<>();
String[] letterMap = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

public List<String> letterCombinations(String digits) {
    backtracking(digits, letterMap, "", 0);
    return res;
}

public void backtracking(String digits, String letterMap[], String path, int index) {
    //确定终止条件,index表示的是遍历到digits的哪一位
    if (index == digits.length()) {
        res.add(path);
        return;
    }
    //获取当前位
    int digit = digits.charAt(index) - '0';
    //获取当前位所对应的字母,例如 2对应 abc
    String letters = letterMap[digit];
    //单层递归可以理解为俩个集合的组合
    for (int i = 0; i < letters.length(); i++) {
        path += letters.charAt(i);
        backtracking(digits, letterMap, path, index + 1);
        path = path.substring(0, path.length() - 1);
    }
}
相关推荐
iAkuya2 小时前
(leetcode)力扣100 53课程表(深搜+拓扑排序)
算法·leetcode·职场和发展
范纹杉想快点毕业2 小时前
嵌入式通信协议深度解析:从SPI/I2C到CAN总线的完整实现指南嵌入式工程师的炼成之路:从校园到实战的跨越
linux·运维·服务器·数据库·算法
啊阿狸不会拉杆2 小时前
《数字信号处理》第10章-数字信号处理中的有限字长效应
算法·matlab·fpga开发·信号处理·数字信号处理·dsp
week_泽2 小时前
GBDT 算法中构建第一个弱学习器(CART 回归树)-计算示例
学习·算法·回归·gbdt
傻小胖2 小时前
16.ETH-状态树-北大肖臻老师客堂笔记
笔记·算法·区块链·哈希算法
张张努力变强2 小时前
C++ 类和对象(五):初始化列表、static、友元、内部类等7大知识点全攻略
开发语言·数据结构·c++·算法
老鼠只爱大米2 小时前
LeetCode经典算法面试题 #23:合并K个升序链表(分支法、优先队列等多种实现方案详细解析)
算法·leetcode·链表·优先队列·多路归并·分治法·合并链表
啵啵鱼爱吃小猫咪2 小时前
机器人几何雅可比与解析雅可比
人工智能·学习·算法·机器学习·matlab·机器人
养军博客2 小时前
C语言五天速成(可用于蓝桥杯备考)
c语言·数据结构·算法