ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AlgoNote 算法通关手册:枚举算法(Enumeration Algorithm)详解与实战

AlgoNote 算法通关手册:枚举算法(Enumeration Algorithm)详解与实战 教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载导读本文是「算法通关手册」第 7 章《算法》的开篇内容系统讲解最基础、最直接的搜索方法——枚举算法穷举算法。你将掌握枚举算法的核心思想、三步解题套路、常用优化手段并通过「百钱买百鸡」、两数之和、统计平方和三元组等经典例题学会如何写出先能过、再优化的正确解为后续学习哈希表、双指针、动态规划等更高效的算法范式打好基础。1. 枚举算法简介枚举算法Enumeration Algorithm又称穷举算法是指根据问题的特点逐一列出所有可能的解并与目标条件进行比较找出满足要求的答案。枚举时要确保不遗漏、不重复。枚举算法的核心思想非常简单遍历所有可能的状态逐个判断是否满足条件找到符合要求的解。由于需要遍历所有状态枚举算法在问题规模较大时效率较低。但它也有两个非常明显的优点实现简单易于编程和调试。基于穷举所有情况正确性容易验证——解一定在枚举范围内只要条件判断无误就不会漏解。因此枚举算法常用于小规模问题或作为其他算法的辅助工具通过枚举部分信息来提升主算法的效率。例如在哈希表解法中先用枚举遍历数组元素再用哈希表加速查另一半的过程就是典型的枚举 数据结构加速组合。2. 枚举算法的解题思路2.1 枚举算法的通用步骤枚举算法是最简单、最基础的搜索方法通常是遇到问题时的首选方案。由于实现简单我们可以先用枚举算法尝试解决问题再考虑是否需要优化。枚举算法的基本步骤如下明确需要枚举的对象、枚举范围和约束条件。逐一枚举所有可能情况判断是否满足题意。思考如何提升枚举效率。其中第三步是枚举算法进阶的关键。提升效率的常用方法有抓住问题本质尽量缩小状态空间例如利用约束条件直接推导出部分变量减少循环层数。增加约束条件减少无效枚举例如根据上界提前终止循环、跳过明显不可能的解。利用某些问题特有的性质例如对称性、单调性等避免重复计算。2.2 枚举算法的简单应用百钱买百鸡以经典的「百钱买百鸡问题」为例问题公鸡 5 元/只母鸡 3 元/只小鸡 1 元/3 只。用 100 元买 100 只鸡问各买多少只第 1 步确定枚举对象和范围枚举对象公鸡数 $x$母鸡数 $y$小鸡数 $z$枚举范围$0 \le x, y, z \le 100$约束条件$5x 3y \frac{z}{3} 100$ 且 $x y z 100$且 $z$ 必须是 3 的倍数第 2 步暴力枚举三重循环class Solution: def buyChicken(self): for x in range(101): for y in range(101): for z in range(101): if z % 3 0 and 5 * x 3 * y z // 3 100 and x y z 100: print(公鸡 %s 只母鸡 %s 只小鸡 %s 只 % (x, y, z))三重循环共需枚举约 $101^3 \approx 10^6$ 种组合虽然能得出正确答案但效率很低。第 3 步优化枚举效率利用方程 $x y z 100$ 可以推出 $z 100 - x - y$从而减少一重循环再根据价格约束 $5x \le 100$、$3y \le 100$ 进一步缩小枚举范围$x \in [0, 20]$$y \in [0, 33]$。class Solution: def buyChicken(self): for x in range(21): for y in range(34): z 100 - x - y if z % 3 0 and 5 * x 3 * y z // 3 100: print(公鸡 %s 只母鸡 %s 只小鸡 %s 只 % (x, y, z))优化后仅需枚举约 $21 \times 34 \approx 700$ 种组合性能提升三个数量级而代码逻辑几乎一样直观。这正是枚举算法先写暴力正确解再减分支、减范围实践路线的生动体现。3. 枚举算法的经典例题3.1 经典例题两数之和3.1.1 题目链接0001. 两数之和 - 力扣LeetCode3.1.2 题目大意描述给定一个整数数组 $nums$ 和一个整数目标值 $target$。要求在该数组中找出和为 $target$ 的两个整数并输出这两个整数的下标。可以按任意顺序返回答案。说明$2 \le nums.length \le 10^4$。$-10^9 \le nums[i] \le 10^9$。$-10^9 \le target \le 10^9$。只会存在一个有效答案。示例示例 1输入nums [2,7,11,15], target 9 输出[0,1] 解释因为 nums[0] nums[1] 9 返回 [0, 1] 。示例 2输入nums [3,2,4], target 6 输出[1,2]3.1.3 解题思路思路 1枚举算法通过两重循环依次枚举数组中所有可能的下标对 $(i, j)$其中 $i j$判断 $nums[i] nums[j]$ 是否等于 $target$。一旦找到满足条件的下标对即 $nums[i] nums[j] target$立即返回这两个下标 $[i, j]$ 作为答案。思路 1代码class Solution: def twoSum(self, nums: List[int], target: int) - List[int]: # 遍历第一个数的下标 for i in range(len(nums)): # 遍历第二个数的下标只需从i1开始避免和自身重复 for j in range(i 1, len(nums)): # 判断两数之和是否等于目标值 if nums[i] nums[j] target: return [i, j] # 返回下标对 return [] # 如果没有找到返回空列表注意第二个循环从i 1开始天然避免了 $(i, i)$ 这种用同一个元素凑和的情况也避免了 $(i, j)$ 与 $(j, i)$ 的重复枚举——这正是枚举算法不重复要求的体现。思路 1复杂度分析时间复杂度$O(n^2)$其中 $n$ 为数组 $nums$ 的元素数量。空间复杂度$O(1)$。思路 2哈希表优化进阶在 docs/solutions/0001-0099/two-sum.md 的题解中还给出了枚举的经典升级方案枚举 哈希表。遍历数组时对每个 $nums[i]$ 先查字典中是否存在 $target - nums[i]$存在则直接返回下标对不存在则把 $nums[i]$ 及下标存入字典。这样把枚举配对的 $O(n^2)$ 查找降为 $O(1)$ 的哈希查询整体时间复杂度降为 $O(n)$空间复杂度为 $O(n)$。这也是本手册在枚举章节反复强调的枚举部分信息 数据结构加速思想的直接落地。3.2 统计平方和三元组的数目3.2.1 题目链接1925. 统计平方和三元组的数目 - 力扣LeetCode3.2.2 题目大意描述给你一个整数 $n$。要求请你返回满足 $1 \le a, b, c \le n$ 的平方和三元组的数目。说明平方和三元组指的是满足 $a^2 b^2 c^2$ 的整数三元组 $(a, b, c)$。$1 \le n \le 250$。示例示例 1输入 n 5 输出 2 解释 平方和三元组为 (3,4,5) 和 (4,3,5)。示例 2输入n 10 输出4 解释平方和三元组为 (3,4,5)(4,3,5)(6,8,10) 和 (8,6,10)。3.2.3 解题思路思路 1枚举算法直接枚举 $a$ 和 $b$计算 $c^2 a^2 b^2$判断 $c$ 是否为整数且 $1 \le c \le n$如果满足条件则计数加一最后返回总数。该方法时间复杂度为 $O(n^2)$。注意为避免浮点误差可以用 $\sqrt{a^2 b^2 1}$ 代替 $\sqrt{a^2 b^2}$这样判断 $c$ 是否为整数更安全。原理是相邻两个完全平方正数之间的距离一定大于 $1$给被开方数加 $1$ 后再向下取整可以消除浮点运算的舍入误差对是否整除判断的干扰。思路 1代码class Solution: def countTriples(self, n: int) - int: cnt 0 # 统计满足条件的三元组个数 for a in range(1, n 1): # 枚举 a for b in range(1, n 1): # 枚举 b # 计算 c注意加 1 防止浮点误差 c int(sqrt(a * a b * b 1)) # 判断 c 是否在范围内且 a^2 b^2 c^2 if c n and a * a b * b c * c: cnt 1 # 满足条件计数加一 return cnt # 返回最终统计结果思路 1复杂度分析时间复杂度$O(n^2)$。空间复杂度$O(1)$。从示例可以看出(3,4,5) 与 (4,3,5) 被分别计数——枚举 $(a, b)$ 有序对天然覆盖了这类对称解不需要额外去重逻辑这正是枚举遍历所有状态带来的正确性保障。4. 枚举算法的更多实战场景除了上述两道例题本手册还在不同章节收录了多个枚举 剪枝的实战题目可在 docs/00_preface/00_06_categories_list.md 的「枚举算法题目」列表中找到完整题单0204. 计数质数枚举因子判断质数再配合埃氏筛等思想优化见 docs/solutions/0200-0299/count-primes.md。2427. 公因子的数目利用公因子不会超过最大公约数这一性质把枚举范围从 $[1, min(a, b)]$ 缩小到 $[1, gcd(a, b)]$对应题解见 docs/solutions/2400-2499/number-of-common-factors.md。2249. 统计圆内格点数目先遍历所有圆求出最小/最大的 $x$、$y$ 坐标范围以缩小搜索框再枚举坐标点判断是否落在圆内对应题解见 docs/solutions/2200-2299/count-lattice-points-inside-a-circle.md。LCR 180. 文件组合通过枚举起点与终点构造连续正整数序列配合双指针优化题解见 docs/solutions/LCR/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof.md。这些题目展示了枚举算法在不同领域的通用性无论是数论因子、几何格点还是区间构造核心套路都是明确对象与范围 → 逐一枚举判断 → 利用问题性质缩小状态空间。5. 总结枚举算法通过遍历所有可能状态来寻找解优点是实现简单、思路直接、正确性易于验证缺点是在问题规模增大时时间开销迅速上升往往无法满足效率要求。它适用于规模较小、可快速验证答案的问题或作为基线方案、结果校验与对拍工具。实战中应尽量结合以下手段显著提升效率剪枝添加约束、提前判定不可能的情况缩小搜索空间利用对称性、边界与不变量如百钱买百鸡中通过方程消元、公因子问题中缩小到 $gcd$ 范围降维与变量替换用等式关系减少循环层数避免重复计算如两数之和中从i 1开始枚举。实践建议是先写出「能过的暴力正确解」再围绕「减分支、减范围、减重算」迭代优化当复杂度仍难以接受时考虑切换到更合适的范式例如哈希加速、双指针与滑动窗口、二分查找、分治、动态规划或图算法等。本手册后续章节如递归、分治、回溯、贪心、动态规划正是这些更高级范式的系统讲解。练习题目0001. 两数之和0204. 计数质数1925. 统计平方和三元组的数目2427. 公因子的数目LCR 180. 文件组合2249. 统计圆内格点数目完整的枚举算法题单含标签与难度分级可参考 docs/00_preface/00_06_categories_list.md 中的「枚举算法题目」章节配套代码与更多数据结构、算法实现可继续翻阅本仓库的 codes/python 目录。赞分享教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载相关推荐AlgoNote 算法通关手册KMP 字符串匹配算法详解与 Python 实战AlgoNote 算法通关手册KMP 字符串匹配算法详解与 Python 实战 本文是「算法通关手册」字符串专题的核心篇章系统讲解 KMPKnuth Mo教程文档知识库AlgoNote 算法通关手册栈Stack基础详解与 Python 实现AlgoNote 算法通关手册栈Stack基础详解与 Python 实现 本文是「算法通关手册」第 3 章《栈、队列与哈希表》的开篇系统讲解栈的核心概念教程文档知识库AlgoNote 算法通关手册双端队列Deque详解与循环双端队列实战AlgoNote 算法通关手册双端队列Deque详解与循环双端队列实战 双端队列DequeDouble Ended Queue是「算法与数据结构」学教程文档知识库上一篇League-Toolkit英雄联盟玩家的终极智能助手完全指南下一篇如何在Chrome浏览器中实现高效二维码处理一键生成与安全识别创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表