LeetCode算法题解(回溯)|LeetCode216. 组合总和 III、LeetCode17. 电话号码的字母组合

一、|LeetCode216. 组合总和 III

题目链接:216. 组合总和 III

题目描述:

找出所有相加之和为 nk个数的组合,且满足下列条件:

  • 只使用数字1到9
  • 每个数字 最多使用一次

返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例 1:

复制代码
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。

示例 2:

复制代码
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。

示例 3:

复制代码
输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

提示:

  • 2 <= k <= 9
  • 1 <= n <= 60

算法分析:

利用回溯算法,首先创建一个二维数组来存放所有合理组合的结果集,用一个一维数组来搜索所有组合。

然后通过递归来纵向遍历组合里的每个元素。

递归参数:每个元素开始的位置坐标startInt,组合中的所有元素总和。

递归结束条件:如果组合的长度等于规定长度K,无论组合总和是否等于N都要返回。

然后用for循环横向遍历从startInt开始到9,

每层for循环,将对应元素i插入组合,同时总和sum也要加上i,然后递归下一层。

递归之后就是回溯,要将当前的元素i从组合中拿出来,sum也要减掉i,再进行下一层for循环。

代码如下:

cpp 复制代码
class Solution {
    List<List<Integer>>result = new ArrayList<>();//用来存放所有组合的结果集
    LinkedList<Integer>path = new LinkedList<>();//用来寻找每种合理组合
    int K;
    int N;
    public void backTraving(int startInt, int sum) {//递归纵向遍历组合的每个元素
        if(path.size() == K) {//如果组合长度等于K,无论组合总和是否等于n都要推出递归
            if(sum == N) result.add(new LinkedList(path));//如果组合总和等于n就将组合放入结果集然后返回
            return;
        }
        for(int i = startInt; i <=9; i++) {//for循环横向遍历1~9
            path.add(i);
            sum += i;
            backTraving(i + 1, sum);//递归
            //回溯
            sum -= i;
            path.removeLast();
        }
    }
    public List<List<Integer>> combinationSum3(int k, int n) {
        K = k;
        N = n;
        backTraving(1, 0);
        return result;
    }
}

二、LeetCode17. 电话号码的字母组合

题目链接:17. 电话号码的字母组合

题目描述:

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

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

示例 1:

复制代码
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

复制代码
输入:digits = ""
输出:[]

示例 3:

复制代码
输入:digits = "2"
输出:["a","b","c"]

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字。

算法分析:

利用回溯算法。

递归纵向遍历字符串digits的每个数字字符。

传递参数:当前组合的长度;

递归结束条件:如果当前组合长度等于digits的长度,将组合放入结果集然后返回。

然后横向遍历每个数字字符所映射的每个字符,将字符依次插入组合,后递归,再删除。

代码如下:

cpp 复制代码
class Solution {
    List<String>result = new ArrayList<String>();//用来存放结果集
    StringBuilder path = new StringBuilder();//用来搜索所有组合
    int len;//字符串长度
    public void backTraving(String digits, int index) {//递归纵向遍历字符串每个数字字符
        if(index == len) {
            result.add(path.toString());
            return;
        }
        switch(digits.charAt(index)) {//横向遍历每个字符所映射的字符,然后递归回溯
            case '2':
                {
                    path.append('a');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('b');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('c');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    break;
                }
            case '3':
            {
                    path.append('d');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('e');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('f');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    break;
                }
            case '4':
            {
                    path.append('g');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('h');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('i');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    break;
                }
            case '5':
            {
                    path.append('j');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('k');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('l');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    break;
                }
            case '6':
            {
                    path.append('m');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('n');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('o');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    break;
                }
            case '7':
            {
                    path.append('p');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('q');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('r');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('s');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    break;
                }
            case '8':
            {
                    path.append('t');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('u');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('v');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    break;
                }
            case '9':
            {
                    path.append('w');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('x');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('y');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    path.append('z');
                    backTraving(digits, index + 1);
                    path.deleteCharAt(index);
                    break;
                }
            default:
                break;
        }
    }
    public List<String> letterCombinations(String digits) {
        len = digits.length();
        if(len == 0) return result;
        backTraving(digits, 0);
        return result;
    }
}

总结

只要掌握了回溯的真正用法并不是很难!

相关推荐
禹凕12 分钟前
滑动窗口算法实战指南
python·算法
evans在进步15 分钟前
Tomcat NIO 工作原理详解:从 Acceptor、Poller 到容器处理链
java·tomcat·nio
DisonTangor19 分钟前
【腾讯混元雪耻归来】 Hy4 preview:770B 参数 MoE 旗舰模型,1M 上下文全面开源
人工智能·算法·开源·aigc·腾讯云·腾讯云ai代码助手
明月_清风1 小时前
从二叉树到 B+ 树:一文搞懂工程中「树」的演化之道
数据结构·算法·go
渡我白衣2 小时前
并查集:基础认识与模拟实现
android·java·javascript·数据结构·c++·算法·并查集
电商API_180079052472 小时前
电商商品价格监控工具淘宝京东商品价格抓取API项目实操分享
java·大数据·开发语言·前端·数据挖掘
zzzll11112 小时前
深度剖析:HashMap 并发死循环与 ConcurrentHashMap 两代演进全解
java·开发语言
秋名RG2 小时前
2026/5/27 生产事故复盘与整改方案
java
hetao17338372 小时前
2026-09-01~09-04 hetao1733837 的刷题记录
c++·算法
Evand J2 小时前
【MATLAB例程,图像滤波5】 反谐波均值滑动窗口滤波(CHMF)图像降噪与质量评价,附代码下载链接
图像处理·算法·计算机视觉·matlab·均值算法·滑动窗口滤波·均值滑动