当前位置: 首页 > news >正文

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

目录

一、LeetCode 78:子集

题目描述

核心思路(回溯法)

完整代码

关键解析

二、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控制遍历起点,避免重复无重复元素的幂集生成
电话号码的字母组合不同数字对应的字母按顺序拼接数字到字母的映射,按顺序处理每个数字多组元素的有序组合生成

总结

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

  • 子集问题帮助你理解如何处理「每个元素的选 / 不选决策」
  • 电话号码的字母组合帮助你理解「多组元素的有序拼接」
http://www.jsqmd.com/news/599267/

相关文章:

  • 安卓跑步打卡项目App源码分享:内含完整源码与简易开发文档
  • 激光技术在多物理场耦合应用中的案例分析:从增材制造到激光打孔与抛光的研究实例集萃
  • 用SolidWorks设计3D打印机:这些零件建模技巧能省你80%时间
  • 终极指南:解决Realtek 8922AE WiFi 7网卡驱动固件版本不匹配问题
  • 微信聊天记录持久化:基于本地解析技术的个人数据管理方案
  • 2026届必备的AI科研平台实际效果
  • 单机环境下的K8s快速部署与Kuboard实战:从零搭建Nginx服务
  • 20260406 之所思 - 人生如梦
  • 从零开始:手把手教你用Arduino和Grbl搭建自己的桌面CNC(附源码导读)
  • DevOps 实践与自动化:从开发到运维的无缝衔接
  • 低压无感BLDC方波控制,代码全部源码,方便调试移植,通用性极高,支持ADC方案,最高电转速1...
  • 如何永久保存微信聊天记录并挖掘数据价值?WeChatMsg全攻略
  • 两级光伏并网低电压穿越仿真研究
  • 自定义安卓图标样式:手把手教你用overlay修改framework-res,避开常见坑
  • 中国AI Agent发展现状与生态分析
  • 微秒制造背景下超快激光与物质作用机理研究:COMSOL仿真飞秒激光烧蚀石英玻璃的实践与展望
  • 2025届必备的十大AI辅助写作平台解析与推荐
  • 【OpenCode】npm命令安装opencode一直转圈圈【已解决】
  • 磁链观测器在vesc中的移植实践:实现零速闭环启动,全方位学习资源呈现
  • LangGraph Node底层逻辑教程(非常详细),从入门到精通,看这篇就够了!
  • 手把手教你用Vivado IBERT给光模块‘体检’:从SFP连接器到误码率报告的完整实战
  • RetDec反编译神器:从零开始掌握二进制代码逆向分析
  • Debian 12 内网求生记:手把手搞定1Panel离线安装与Docker启动(附iptables补丁)
  • L-BFGS算法在自动驾驶路径平滑中的实践与优化
  • 从防御者视角看攻击:我用AntSword复现了一次真实的Webshell入侵,并总结了5条防护建议
  • CentOS 7 离线部署NVIDIA Container Toolkit全攻略
  • lil_tea c++ 2023 style guide
  • Agent框架选型入门教程(非常详细):AgentScope VS DeepAgents,看这篇就够了!
  • [CF2195D] Absolute Cinema 题解
  • Linux内核中的内存屏障技术详解