如何设计优秀的公司网站在网站中搜索关键字
如何设计优秀的公司网站,在网站中搜索关键字,电子版简历免费模板,wordpress 免签约回溯算法是一种基于深度优先搜索#xff08;DFS#xff09;的暴力搜索算法#xff0c;核心思想是「尝试所有可能的路径#xff0c;走不通就回头」#xff0c;适用于求解「组合、排列、子集、分割、棋盘」等需要枚举所有可能解的问题。一、回溯算法的核心概念1. 核心思想「…回溯算法是一种基于深度优先搜索DFS的暴力搜索算法核心思想是「尝试所有可能的路径走不通就回头」适用于求解「组合、排列、子集、分割、棋盘」等需要枚举所有可能解的问题。一、回溯算法的核心概念1. 核心思想「选择」在当前步骤选择一个可行的选项「递归」基于当前选择进入下一层继续选择「回溯」递归返回后撤销当前选择回到上一步尝试其他选项「剪枝」提前排除不可能的路径减少无效搜索优化效率。2. 适用场景组合问题如组合总和、电话号码的字母组合排列问题如全排列、下一个排列子集问题如子集、子集 II分割问题如分割回文串、复原 IP 地址棋盘问题如 N 皇后、数独。3. 算法框架通用模板// 全局/参数结果集 临时路径 ListListInteger result new ArrayList(); ListInteger path new ArrayList(); public void backtrack(选择列表, 起始位置/约束条件) { // 1. 终止条件找到一个合法解加入结果集 if (满足终止条件) { result.add(new ArrayList(path)); // 注意必须复制path不能直接加引用 return; } // 2. 遍历所有可选选项 for (int i 起始位置; i 选择列表长度; i) { // 3. 剪枝排除无效/重复选项关键优化 if (不满足条件) { continue; // 跳过当前选项 } // 4. 做出选择将当前选项加入临时路径 path.add(选择列表[i]); // 5. 递归进入下一层搜索 backtrack(选择列表, 新的起始位置); // 6. 回溯撤销选择回到上一步 path.remove(path.size() - 1); } }二、回溯算法的关键细节1. 终止条件的设计终止条件需根据问题目标定义组合问题路径和 / 长度达到目标如组合总和的 target0排列问题路径长度等于元素总数子集问题遍历完所有元素无需额外终止遍历过程中所有路径都是解。2. 「去重」的两种场景回溯中最常见的坑是结果集重复需根据问题类型处理场景 1元素可重复但结果不可重复如组合总和 II4. 剪枝优化提前排除不可能的路径减少递归次数5. 结果集的保存三、经典题型分类与解题思路题型核心特点关键处理示例题目组合问题不考虑顺序元素可 / 不可重用 startIndex 控制范围排序去重组合总和、组合总和 II排列问题考虑顺序元素可 / 不可重用 used 数组标记已选排序去重全排列、全排列 II子集问题所有可能的子集遍历过程中直接保存所有路径子集、子集 II分割问题按规则分割字符串验证子串合法性如回文startIndex 分割分割回文串、复原 IP 地址棋盘问题多约束条件如 N 皇后验证当前位置合法性逐行 / 列递归N 皇后、解数独四、经典例题解析组合总和 II题目要求给定候选数组有重复元素找出所有和为 target 的组合每个元素只能用一次结果无重复组合。完整代码class Solution { public ListListInteger combinationSum2(int[] candidates, int target) { ListListInteger zong new ArrayList(); ListInteger bushi new ArrayList(); Arrays.sort(candidates); hueisu(candidates,target,zong,bushi,0); return zong; } public void hueisu(int[] candidates, int target,ListListInteger zong,ListInteger bushi,int index){ if(target 0){ zong.add(new ArrayList(bushi)); return; } for(int i index;i candidates.length;i){ if(i index candidates[i] candidates[i-1]){ continue; } if(candidates[i] target){ break; } bushi.add(candidates[i]); hueisu(candidates, target - candidates[i], zong, bushi, i 1); bushi.remove(bushi.size() - 1); } } }核心要点五、回溯算法的解题步骤六、常见易错点总结掌握回溯的通用模板后通过经典题型反复练习组合、排列、子集、分割、棋盘即可快速应对各类回溯问题。步骤 1先对数组排序Arrays.sort()步骤 2同层跳过重复元素核心if (i startIndex candidates[i] candidates[i-1]) { continue; // 跳过同层重复保留不同层重复 }场景 2元素不可重复使用如排列问题方法用boolean[] used数组标记已使用的元素if (used[i]) { continue; // 跳过已使用的元素 } used[i] true; // 标记使用 backtrack(...); used[i] false; // 回溯取消标记3. 「起始位置」的作用组合 / 子集问题startIndex控制「不回头选」避免重复组合如 [1,2] 和 [2,1] 视为同一组合排列问题无需startIndex但需used数组标记已选元素。排序后剪枝如组合总和中若当前元素 剩余 target直接break后续元素更大错误写法result.add(path)path 是引用回溯后会被修改正确写法result.add(new ArrayList(path))复制 path 的当前内容与原引用解耦。合法性剪枝如分割回文串中若当前子串不是回文直接跳过。排序为去重和剪枝提供基础同层去重i startIndex保证只跳过同层重复不影响不同层剪枝candidates[i] target提前终止循环减少无效递归元素仅用一次递归参数传i1而非startIndex1。组合总和(对比)class Solution { public ListListInteger combinationSum(int[] candidates, int target) { ListListInteger zong new ArrayListListInteger() ; ListInteger buchu new ArrayListInteger(); hueisu(candidates,target,zong,buchu,0); return zong; } public void hueisu(int[] candidates, int target,ListListInteger zong,ListInteger buchu,int index){ if(index candidates.length){ return; } if(target 0){ zong.add(new ArrayListInteger(buchu)); return; } hueisu(candidates,target,zong,buchu,index1); if(target - candidates[index] 0){ buchu.add(candidates[index]); hueisu(candidates,target - candidates[index],zong,buchu,index); buchu.remove(buchu.size() - 1); } } }明确解的形式确定结果集如ListListInteger和临时路径如ListInteger定义回溯函数确定参数选择列表、起始位置、约束条件等设计终止条件满足条件时保存解遍历选择列表循环处理每个可选选项剪枝优化排除无效选项提升效率选择 - 递归 - 回溯核心三步完成一次路径探索处理边界如输入为 0、空数组等特殊情况。直接添加路径引用到结果集需复制new ArrayList(path)去重时未排序或误判「同层 / 不同层」重复组合问题误用排列的逻辑如未用 startIndex导致重复组合递归参数错误如组合总和 II 中传startIndex1而非i1未剪枝导致超时如大数组合问题未提前终止循环。回溯算法的核心是「选择 - 递归 - 回溯」本质是暴力搜索所有可能路径去重和剪枝是回溯优化的关键排序是去重的基础不同题型的核心差异在于「起始位置」和「去重方式」组合 / 子集用 startIndex 控范围排序去重排列用 used 数组控重复排序去重结果集保存必须复制路径避免引用修改导致结果错误。