当前位置: 首页 > 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.lryc.cn/news/619356.html

相关文章:

  • BGE:智源研究院的通用嵌入模型家族——从文本到多模态的语义检索革命
  • 海洋通信系统技术文档(1)
  • 高可用实战之Nginx + Apache篇
  • QT常用类解析
  • ubuntu20.04下C++实现点云的多边形区域过滤(2种实现:1、pcl的CropHull滤波器;2、CUDA上实现射线法)
  • 在Ubuntu24.04中使用ssh连接本地git仓库到github远程仓库
  • C++QT HTTP与HTTPS的使用方式
  • 【网络安全测试】OWASP ZAP web安全测试工具使用指导及常用配置(有关必回)
  • Spring事务管理实战:从注解到进阶
  • Spring 源码学习(十)—— DispatcherServlet
  • 【一步AI】模型压缩:减小模型体积与计算量
  • YOLOv8 级联检测:在人脸 ROI 内检测眼镜(零改源码方案)
  • 第十六届蓝桥杯青少组C++省赛[2025.8.9]第二部分编程题(1 、庆典队列)
  • Excel怎么筛选重复项?【图文详解】查找/删除重复项?查找重复项公式?如何去重?
  • [QtADS]解析demo.pro
  • HarmonyOS NDK的JavaScript/TypeScript与C++交互机制
  • Electron自定义菜单栏及Mac最大化无效的问题解决
  • XML头部声明发送者信息的实现方法
  • C# 微软依赖注入 (Microsoft.Extensions.DependencyInjection) 详解
  • CV 医学影像分类、分割、目标检测,之【肝脏分割】项目拆解
  • windows常用的快捷命令
  • 机器学习实战·第三章 分类(2)
  • docker 容器内编译onnxruntime
  • git clone 支持在命令行临时设置proxy
  • CV 医学影像分类、分割、目标检测,之【腹腔多器官语义分割】项目拆解
  • 何解决PyCharm中pip install安装Python报错ModuleNotFoundError: No module named ‘json’问题
  • Video_AVI_Packet(2)
  • 基于RTSP|RTMP低延迟视频链路的多模态情绪识别系统构建与实现
  • 日志数据链路的 “搬运工”:Flume 分布式采集的组件分工与原理
  • 进阶向:Python编写自动化邮件发送程序