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

【递归、搜索与回溯算法】穷举、暴搜、深搜、回溯、剪枝

在这里插入图片描述

  • 穷举 vs 暴搜 vs 深搜 vs 回溯 vs 剪枝
  • 一、[全排列](https://leetcode.cn/problems/permutations/description/)
  • 二、[子集](https://leetcode.cn/problems/subsets/description/)
  • 结尾

穷举 vs 暴搜 vs 深搜 vs 回溯 vs 剪枝

  1. 穷举:最基础的思想
    • 定义:从所有可能的解中,逐一检查每个候选解是否满足条件,直到找到答案(或确认无解)。
    • 特点:不依赖任何策略,纯粹 “地毯式” 覆盖所有可能性,是最朴素的搜索思想。
  2. 暴搜:穷举的 “实现方式”
    • 定义:“暴力搜索” 的简称,是穷举思想的具体实现,通常指无优化地遍历所有可能解(本质上是 “未优化的穷举”)。
    • 与穷举的关系:穷举是思想,暴搜是这种思想的直接落地方式,两者常被混用,但暴搜更强调 “不做任何优化,硬刚所有可能”。
  3. 深搜:暴搜的 “遍历策略”
    • 定义:深度优先搜索,是暴搜的一种具体遍历方式 —— 优先沿着一条路径 “走到底”,直到无法继续再回溯,换另一条路径探索。
    • 与暴搜的关系:深搜是暴搜的 “优化形式” 之一,它通过明确的遍历顺序避免重复探索同一路径,比 “无规律的暴搜” 更有序。
  4. 回溯:深搜的 “改进版”
    • 定义:在深搜的基础上,增加 “撤销选择” 的操作 —— 当探索到某一步发现当前路径不可能通向解时,不仅退回上一步,还会 “清理当前步骤的影响”,以便重新尝试其他路径。
    • 与深搜的关系:回溯是 “带状态重置的深搜”,是深搜的精细化实现,解决了深搜中 “状态污染” 的问题。
  5. 剪枝:回溯 / 深搜的 “优化手段”
    • 定义:在回溯或深搜过程中,通过提前判断 “当前路径不可能通向解”,直接终止该路径的探索,避免无效分支消耗资源。
    • 与回溯 / 深搜的关系:剪枝是对回溯或深搜的 “效率优化”,不改变其核心逻辑,只减少不必要的计算。

一、全排列

题目描述
在这里插入图片描述

思路讲解
本道题需要我们从给定一个不含重复数字的数组 nums ,返回其所有可能的全排列。通过递归尝试所有可能的元素排列,在每一步选择一个未使用的元素加入当前排列,完成选择后回溯并尝试下一个元素,直到生成所有完整排列。以下是具体的思路:

  • 核心逻辑
    • 全排列的本质是从数组中依次选择元素,每个元素在排列中只能出现一次。通过递归逐层确定排列的每个位置,使用 “选择 - 递归 - 回溯” 的流程遍历所有可能的组合
  • 全局变量
    • path:当前正在构建的排列
    • isuse:记录元素是否已被使用的布尔数组(避免重复选择)
    • ans:存储所有完整排列的结果集(引用传递)
  • 终止条件
    • 当 path 的长度等于 nums 的长度时,说明已生成一个完整排列,将其加入 ans 并返回
  • 递归逻辑
    • 遍历数组中的每个元素,若元素未被使用(isuse[i] == false):
      • 将元素加入 path,标记 isuse[i] = true
      • 继续递归构建下一个位置的元素
      • 递归返回后,将元素从 path 中移除,标记 isuse[i] = false,以便其他分支使用该元素

编写代码

class Solution {vector<vector<int>> ans;bool isuse[7];vector<int> path;int len;
public:void _permute(vector<int>& nums) {if(path.size() == len){ans.push_back(path);return;}for(int i = 0 ; i < len ; i++){if(isuse[i] == false){path.push_back(nums[i]);isuse[i] = true;_permute(nums);path.pop_back();isuse[i] = false;}}}vector<vector<int>> permute(vector<int>& nums) {len = nums.size();memset(isuse,false,sizeof(isuse));_permute(nums);return ans;}
};

二、子集

题目描述
在这里插入图片描述

思路讲解
本道题需要我们根据整数数组 nums ,返回该数组所有可能的子集。逐步选择元素,构建所有可能的子集,通过回溯法在每一步决定是否选择当前元素,最终生成所有不重复的子集。

  • 核心逻辑
    • 子集问题的本质是从数组中选择任意个元素(包括 0 个),形成不重复的集合。递归过程中,对于每个元素,有两种选择:加入当前子集或不加入当前子集,通过遍历所有选择组合生成完整解集。
  • 全局变量
    • path:当前正在构建的子集
    • ans:存储所有子集的结果集
  • 终止条件
    • 当遍历完数组所有元素(pos == nums.size())时,将当前子集 path 加入 ans 并返回。
  • 递归逻辑
    • 不选择当前元素:直接递归处理下一个元素,当前子集不变。
    • 选择当前元素:将 nums[pos] 加入 path,递归处理下一个元素,之后回溯(从 path 中移除该元素)。

编写代码

class Solution {vector<vector<int>> ans;vector<int> path;int len;
public:void _subsets(vector<int>& nums , int pos) {if(pos == len){ans.push_back(path);return;}path.push_back(nums[pos]);_subsets(nums,pos+1);path.pop_back();_subsets(nums,pos+1);}vector<vector<int>> subsets(vector<int>& nums) {len = nums.size();_subsets(nums,0);return ans;}
};

结尾

如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。
希望大家以后也能和我一起进步!!🌹🌹
如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹
在这里插入图片描述

http://www.dtcms.com/a/329796.html

相关文章:

  • 第七章:OLED温湿度显示系统
  • 数据库连接池如何进行空闲管理
  • 光伏板横铺VS竖铺,布局决定发电量!
  • MySQL数据库知识体系总结 20250813
  • iOS混淆工具有哪些?数据安全与隐私合规下的防护实践
  • [ai]垂直agent|意图识别|槽位提取
  • 基于Tensorflow2.15的图像分类系统
  • MySQL三大存储引擎对比:InnoDB vs MyISAM vs MEMORY
  • 【Unity3D】Spine黑线(预乘问题)、贴图边缘裁剪问题
  • Effective C++ 条款39:明智而审慎地使用private继承
  • RabbitMQ:Windows版本安装部署
  • Java研学-RabbitMQ(六)
  • 基于js和html的点名应用
  • B站 韩顺平 笔记 (Day 17)
  • Spring Security 前后端分离场景下的会话并发管理
  • Spring Boot项目调用第三方接口的三种方式比较
  • 【Linux学习|黑马笔记|Day3】root用户、查看权限控制信息、chmod、chown、快捷键、软件安装、systemctl、软连接、日期与时区
  • Go 微服务限流与熔断最佳实践:滑动窗口、令牌桶与自适应阈值
  • NLP学习之Transformer(1)
  • 深度学习(4):数据加载器
  • Redis7学习——Redis的初认识
  • 51c自动驾驶~合集14
  • Docker:快速部署 Temporal 工作流引擎的技术指南
  • 3DM游戏运行库合集离线安装包下载, msvcp140.dll丢失等问题修复
  • 迅雷链接在线解密解析工具系统源码/本地化API/开源
  • 前缀函数的运用
  • Harmony OS 开发入门 第三章
  • Python Day29 CSS样式
  • Protobuf学习(1)—— 初识与安装
  • 代理解决跨域