回溯算法双杀:子集 + 电话号码的字母组合 | 经典模板题解析

目录

[一、LeetCode 78:子集](#一、LeetCode 78:子集)

题目描述

核心思路(回溯法)

完整代码

关键解析

[二、LeetCode 17:电话号码的字母组合](#二、LeetCode 17:电话号码的字母组合)

题目描述

核心思路(回溯法)

完整代码

关键解析

三、两道题核心对比

总结


一、LeetCode 78:子集

题目描述

给你一个整数数组 nums,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。解集不能包含重复的子集。

核心思路(回溯法)

子集问题的本质是对每个元素进行「选 / 不选」的决策:

  1. 不选:跳过当前元素,直接处理下一个元素
  2. :将当前元素加入路径,处理完后续元素后再回溯(移除当前元素)

完整代码

java

运行

复制代码
import java.util.ArrayList;
import java.util.List;

public class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> subsets(int[] nums) {
        backtrack(nums, 0);
        return result;
    }

    private void backtrack(int[] nums, int startIndex) {
        // 每次递归的路径都是一个有效的子集,直接加入结果集
        result.add(new ArrayList<>(path));
        // 遍历从 startIndex 开始的元素,避免重复选择
        for (int i = startIndex; i < nums.length; i++) {
            // 选当前元素
            path.add(nums[i]);
            // 递归处理下一个元素(避免重复,i+1)
            backtrack(nums, i + 1);
            // 回溯:移除当前元素
            path.remove(path.size() - 1);
        }
    }
}

关键解析

  • 递归终止条件:这里没有单独的终止条件,每次递归的路径都是一个有效的子集(包括空集),直接加入结果集即可。
  • 去重逻辑 :通过 startIndex 控制遍历起点,保证每个元素只被选择一次,避免生成重复的子集。

二、LeetCode 17:电话号码的字母组合

题目描述

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

数字对应的字母映射如下:

  • 2:["a","b","c"]
  • 3:["d","e","f"]
  • 4:["g","h","i"]
  • 5:["j","k","l"]
  • 6:["m","n","o"]
  • 7:["p","q","r","s"]
  • 8:["t","u","v"]
  • 9:["w","x","y","z"]

核心思路(回溯法)

这是典型的组合问题,每个数字对应一组字母,需要按顺序组合不同数字对应的字母:

  1. 用一个哈希表 / 数组保存数字到字母的映射
  2. 递归处理每个数字对应的字母,拼接成完整的组合
  3. 当处理完所有数字时,将拼接好的字符串加入结果集

完整代码

java

运行

复制代码
import java.util.ArrayList;
import java.util.List;

public class Solution {
    // 数字到字母的映射
    private final String[] map = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    List<String> result = new ArrayList<>();
    StringBuilder path = new StringBuilder();

    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) {
            return result;
        }
        backtrack(digits, 0);
        return result;
    }

    private void backtrack(String digits, int index) {
        // 处理完所有数字,拼接完成
        if (index == digits.length()) {
            result.add(path.toString());
            return;
        }
        // 获取当前数字对应的字母
        String letters = map[digits.charAt(index) - '0'];
        // 遍历每个字母,尝试拼接
        for (char c : letters.toCharArray()) {
            path.append(c);
            // 处理下一个数字
            backtrack(digits, index + 1);
            // 回溯:移除当前字母
            path.deleteCharAt(path.length() - 1);
        }
    }
}

关键解析

  • 映射处理:用数组直接映射数字到字母,避免哈希表的额外开销,访问更高效。
  • 递归终止条件 :处理完所有数字(index == digits.length()),此时路径拼接完成,加入结果集。
  • 拼接优化 :使用 StringBuilder 代替字符串拼接,减少字符串生成的开销,提升性能。

三、两道题核心对比

表格

题目 核心逻辑 关键技巧 适用场景
子集 每个元素选 / 不选,生成所有可能 startIndex 控制遍历起点,避免重复 无重复元素的幂集生成
电话号码的字母组合 不同数字对应的字母按顺序拼接 数字到字母的映射,按顺序处理每个数字 多组元素的有序组合生成

总结

这两道题是回溯算法的经典入门案例,核心逻辑都是「选择 - 递归 - 回溯」:

  • 子集问题帮助你理解如何处理「每个元素的选 / 不选决策」
  • 电话号码的字母组合帮助你理解「多组元素的有序拼接」
相关推荐
wuweijianlove1 小时前
算法验证与性能测试的统一框架设计的技术3
算法
LabVIEW开发1 小时前
LabVIEW插值应用
算法·labview·labview知识·labview功能·labview程序
yuanmazhiwu2 小时前
计算机毕业设计:Python智慧出行数据分析与模式识别系统 Django框架 可视化 数据分析 PyEcharts 交通 深度学习(建议收藏)✅
人工智能·python·算法·数据分析·django·flask·课程设计
沉鱼.442 小时前
第十一届题目
算法
C雨后彩虹2 小时前
箱子之字形摆放
java·数据结构·算法·华为·面试
小肝一下4 小时前
每日两道力扣,day5
数据结构·c++·算法·leetcode·职场和发展·hot100
jiang_changsheng4 小时前
亚马逊的2026年最新算法变革自然流量分发机制“文本匹配”到“多模态意图理解”的范式革命
大数据·算法·推荐算法
OOJO9 小时前
c++---list介绍
c语言·开发语言·数据结构·c++·算法·list
别或许10 小时前
1、高数----函数极限与连续(知识总结)
算法