代码随想录算法训练营第22天 | 第七章 回溯算法part01

OpenCV 算法梳理分析 本文系统梳理了OpenCV的核心算法体系,从模块架构到具体函数实现。OpenCV采用分层设计,包含基础I/O、图像处理、特征检测、视频分析和智能算法五大层次,所有模块基于统一的Mat数据结构。重点分析了imgproc模块的8类图像处理算法(滤波、形态学、阈值化等),features2d模块的特征检测与匹配流程(SIFT/ORB等算法对比),以及objdetect、video、calib3d等模块的核心功能。针对不同场景提供了算法选型建议,如高斯噪声推荐GaussianBlur,特征匹配推荐ORB+Flann 阅读详情


回溯算法

回溯法也可以叫做回溯搜索法,它是一种搜索的方式。
回溯是递归的副产品,只要有递归就会有回溯。
所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数。
因为回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案。

解决的问题:

  1. 组合:N个数里面按一定规则找出k个数的集合
  2. 分割:一个字符串按一定规则有几种切割方式
  3. 子集:一个N个数的集合里有多少符合条件的子集
  4. 排列:N个数按一定规则全排列,有几种排列方式
  5. 棋盘问题:N皇后,解数独等等
  6. 其他

组合和排列:例如:{1, 2} 和 {2, 1} 在组合上,就是一个集合,因为不强调顺序,而要是排列的话,{1, 2} 和 {2, 1} 就是两个集合了。
记住组合无序,排列有序,就可以了。

如何理解回溯法

回溯法解决的问题都可以抽象为树形结构,是的,我指的是所有回溯法的问题都可以抽象为树形结构!
因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度就构成了树的深度。
递归就要有终止条件,所以必然是一棵高度有限的树(N叉树)。
这块可能初学者还不太理解,后面的回溯算法解决的所有题目中,我都会强调这一点并画图举相应的例子,现在有一个印象就行。

回溯法模板

  1. 回溯函数模板返回值以及参数
    回溯算法中函数返回值一般为void。
    再来看一下参数,因为回溯算法需要的参数可不像二叉树递归的时候那么容易一次性确定下来,所以一般是先写逻辑,然后需要什么参数,就填什么参数。
    回溯函数伪代码如下:
void backtracking(参数)
  1. 回溯终止条件
    树中就可以看出,一般来说搜到叶子节点了,也就找到了满足条件的一条答案,把这个答案存放起来,并结束本层递归。
if(终止条件){
  存放结果;
  return;
}
  1. 回溯搜索的遍历过程

回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。

在这里插入图片描述

for(选择:本层集合中元素(树中节点孩子的数量就是集合的大小)){
   处理节点;
   backtracking(路径, 选择列表);//递归
   回溯, 撤销处理结果

}

回溯总模板

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

77.组合

Leetcode链接
思路:因为k=2,所以暴力搜索法是用两层for循环嵌套实现,回溯法用递归解决嵌套层数

图中可以发现n相当于树的宽度,k相当于树的深度。

在这里插入图片描述

class Solution {
private:
    vector<vector<int>> result; // 存放集合
    vector<int> path;           // 存放单一结果
    void backtracking(int n, int k, int startIndex) {
        // 终止条件
        if (path.size() == k) {
            result.push_back(path);
            return;
        }
        for (int i = startIndex; i <= n; i++) {
            path.push_back(i);
            backtracking(n, k, i + 1); // 递归:纵向遍历,纵向的startIndex从i+1开始遍历
            path.pop_back(); // 回溯,撤销处理节点
        }
    }
public:
    vector<vector<int>> combine(int n, int k) {
        result.clear();
        path.clear();
        backtracking(n, k, 1);
        return result;
    }
};

剪枝优化

n = 4,k = 4的话,那么第一层for循环的时候,从元素2开始的遍历都没有意义了。 在第二层for循环,从元素3开始的遍历都没有意义了。

  1. 已经选取的元素为path.size()
  2. 还需选取的元素:k-path.size()
  3. 列表剩余元素:n-i >= 还需选取的元素:k-path.size()
  4. 则n集合里 最多从 起始位置i 开始遍历,其中 i<=n-(k-path.size())+1

EX:n=4, k=3 若path.size()=1(选取了一个元素),则 i <=3 (若遍历到i=4,不可能满足 k=3 的:[1,4])

在这里插入图片描述

216.组合总和Ⅲ

Leetcode链接

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(int k, int n, int sum, int startIndex) {
        if (sum > n)
            return;
        if (path.size() == k) {
            if (sum == n) {
                result.push_back(path);
                return;
            }
        }
        for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {
            path.push_back(i);
            sum += i;
            backtracking(k, n, sum, i + 1);
            sum -= i;
            path.pop_back();
        }
    }

public:
    vector<vector<int>> combinationSum3(int k, int n) {
        result.clear();
        path.clear();
        backtracking(k, n, 0, 1);
        return result;
    }
};

17.电话号码的字母组合

Leetcode链接

思路:
数字和字母如何映射:定义一个map or 二维数组:

const string letterMap[10]={
    "",//0
    "",//1
    "abc",//2
    "def",//3
    "ghi",
    "jkl",
    "mno",
    "pqrs",
    "tuv",
    "wxyz"//9
};
class Solution {
private:
    const string letterMap[10] = {
        "",     
        "", 
        "abc", 
        "def",
        "ghi",  // 4
        "jkl",  // 5
        "mno",  // 6
        "pqrs", // 7
        "tuv",  // 8
        "wxyz", // 9
    };

public:
    vector<string> result;
    string s;
    void backtracking(const string& digits, int index) {
        if (index == digits.size()) {
            result.push_back(s);
            return;
        }
        int digit = digits[index] - '0';
        string letters = letterMap[digit];
        for (int i = 0; i < letters.size(); i++) {
            s.push_back(letters[i]);
            backtracking(digits, index + 1);
            s.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
        s.clear();
        result.clear();
        if (digits.size() == 0) {
            return result;
        }
        backtracking(digits, 0);
        return result;
    }
};`

总结

视觉机器人抓取实战:从物体定位到抓取估计的完整流程解析(附Python代码示例) 本文详细解析了视觉引导机器人抓取的完整技术流程,涵盖从物体定位、位姿估计到抓取估计的核心步骤。通过Python代码示例,演示了如何使用Open3D等工具进行点云处理、平面分割、PCA与ICP位姿估计,以及基于几何启发式的抓取生成方法,为机器人视觉抓取开发提供了清晰的实战指南。 阅读详情

相关推荐

机器学习算法全景手稿:按图索骥,手写三大类六大算法

任务类型算法名称核心优势致命短板适用数据场景分类逻辑回归概率解释强、训练极快线性边界,无法处理复杂非线性金融风控、点击率预估分类KNN无训练过程、多分类友好预测极慢、内存占用大小样本图像识别、推荐初筛分类SVM高维有效、泛化能力强(核技巧)百万级样本训练极慢、调参复杂文本分类、人脸检测分类决策树可解释性极强、可处理缺失值极其容易过拟合(需剪枝)医疗诊断、规则提取回归线性回归计算简单、可解释性强对异常值敏感、假设线性关系房价预测、销量预测聚类K-Means。

suny8的专栏 90

代码随想录算法训练营day22(python版)|第七章 回溯算法part01 |77. 组合·216.组合总和III·17.电话号码的字母组合

如果从某个 i 开始,后面剩下的数字总数都不够把“还差的”补齐,就没必要试了。其实在讲解二叉树的时候,就给大家介绍过回溯,这次正式开启回溯算法,大家可以先看视频,对回溯算法有一个整体的了解。对着 在 回溯算法理论基础 给出的 代码模板,来做本题组合问题,大家就会发现 写回溯算法套路。在回溯算法解决实际问题的过程中,大家会有各种疑问,先看视频介绍,基本可以解决大家的疑惑。本题关于剪枝操作是大家要理解的重点,因为后面很多回溯算法解决的题目,都是这个剪枝套路。1→再选 2 → [1,2] 满了,存;

qq_43752779的博客 949

点云处理实操(四) -PCL中的点云三角化

点云处理实操(四) -PCL中的点云三角化

cangqiongxiaoye的博客 917

day 22 第七章 回溯算法part01代码随想录算法训练营71期

多个集合间的组合问题,每个数字对应独立的字符集合。:输入为空字符串时需特殊处理。

gu_xin_的博客 48

代码随想录算法训练营DAY22第七章 回溯算法part01

代码代码随想录算法训练营DAY22第七章 回溯算法part01

2401_88089822的博客 53

代码随想录算法训练营22| 669. 修剪二叉搜索树;108.将有序数组转换为二叉搜索树;538.把二叉搜索树转换为累加树

代码代码随想录算法训练营22| 669. 修剪二叉搜索树;108.将有序数组转换为二叉搜索树;538.把二叉搜索树转换为累加树。

weixin_44647325的博客 185

数据库连接算法详解:从基础概念到嵌套循环优化

2.重复键在归并连接中的处理:排序归并连接遇到相同键时,需要保存或回溯同一键对应的记录组,然后输出笛卡尔积。(2)外连接:即使一方没有数据,也保留该侧数据,用NULL填充。对S中的键计算哈希值;(3)连接基数:连接结果的行数可能远大于任意一张输入表。设外表有R个页面,内表S个页面,比较次数O(R+R*S)5.哈希连接的限制:最适用于等值连接,不直接适用于比较。(1)build阶段:对较小的关系R建立哈希表。(1)内连接:只保留两张表之中能够匹配的内容。若R有M行,S有N行,则比较次数为O(MN)

jiangxiaohanya的博客 231

小红书 算法一面 十一

例如 **Soft MoE** 采用这种方式,大幅提升负载均衡性,但会增加计算开销。- **熵正则化**:直接最大化门控概率分布的熵,熵越大表示分布越均匀,公式为 $\mathcal{L}_{ent} = -\frac{1}{N}\sum_{i=1}^N\sum_{k=1}^K p_{ik}\log p_{ik}$。- **核心原理**:源自 **GShard** 和 **Switch Transformer**,通过最小化专家选择概率分布的熵,迫使门控网络给每个专家分配相近的 token 数量。

XLYcmy的博客 436

LeetCode 1. 两数之和 | 从暴力枚举到哈希表最优解 + 空间换时间思想全复盘

文章摘要 题目要求在数组中找到两数之和等于目标值的下标。核心思路是优化查找效率: 暴力法:双重循环枚举所有数对,时间复杂度O(n²),效率低但易实现。 哈希表优化:利用哈希表O(1)查找特性,遍历时存储已访问元素,每次计算差值并查询,时间复杂度降至O(n)。关键细节是先查后存,避免自匹配。 代码实现:哈希表法通过一次遍历完成,空间换时间,边界处理需注意空数组和不足两元素的情况。 常见错误:内层循环起始点、哈希表键值设计、立即返回结果等易错点需警惕。 面试要点:优先选择哈希表解法,解释与暴力法的差异,强调时间

yc2284238579的博客 254

算法日常・每日刷题--<BFS>4

题目摘要: 给定一个由'X'和'O'组成的矩阵,要求捕获所有被'X'完全包围的'O'区域(即不与边界连通的区域),并将其替换为'X'。解法核心是逆向处理: 标记边界连通区域:遍历矩阵四边,对边界上的'O'进行BFS/DFS,标记所有与之连通的'O'为临时符号(如'.'),表示这些区域未被包围。 批量修改:遍历整个矩阵,将未被标记的'O'(被包围的)改为'X',同时恢复标记的'.'为'O'。 示例: 输入: [['X','X','X','X'], ['X','O','O','X'], ['X','X','O'

2503_92261635的博客 257

10.LeetCode算法习题讲解--滑动窗口--最大连续为一的个数

利用滑动窗口解决最大连续1的个数

Jammy_1的博客 216

AI辅助芯片制造:算法与工程化落地

《国产DRAM龙头长鑫科技上市创纪录,AI技术重塑芯片制造新范式》 国产DRAM龙头企业长鑫科技7月27日登陆科创板,创下3.31万亿元市值,成为A股"一哥"。作为大陆唯一实现DRAM大规模量产的IDM企业,长鑫科技标志着国产存储产业的重要突破。随着AI算力需求激增,DRAM市场迎来高速发展期。AI技术正在深度改变芯片制造模式,在工艺仿真、缺陷检测、设备维护等环节发挥关键作用,显著提升良率和效率。长鑫科技高管推荐的新书《AI辅助芯片制造:算法与工程化落地》系统解析了AI赋能半导体制造的实战方案

weixin_43178406的博客 7339

二刷hot100-70.爬楼梯

dp数组初始化:dp[n+1];

2302_78497251的博客 46

S 曲线加减速算法完整详解(C# 原生实现,无第三方库)

S 曲线加减速是工业运动控制核心轨迹规划算法,相比梯形曲线,依靠约束加加速度 Jerk 实现加速度连续变化,有效消除机械冲击与振动。本文完整讲解七段式 S 曲线原理、阶段推演、时间预规划逻辑,剖析短行程自动裁剪等工程难点。提供无第三方依赖原生 C# 完整实现,内置运动状态机,支持正反方向运动,基于解析多项式实时求解位置、速度、加速度,无积分累积误差。代码可直接用于伺服上位机、模组轨迹发生器,亦可精简移植嵌入式平台。同时对比算法优劣与适用场景,适合工控开发、伺服调试、嵌入式运动算法学习者参考。

工业上位机开发工程师,专注C#底层算法与工控仪器开发。从零手写信号滤波、曲线拟合、机器视觉、排序与密码学哈希,纯原生实现零第三方库,附数学推导与可编译源码,可移植STM32/PLC。 960

Tokenization(分词算法):一切大语言模型的地基

本文深入解析了Tokenization(分词算法)这一大语言模型的基础技术。Tokenization将原始文本切分为模型可处理的子词单元并映射为数字ID,是模型理解文本的第一步。

2301_80194949的博客 197

LeetCode 28. 找出字符串中第一个匹配项的下标(暴力匹配 + KMP 算法详解)

本文介绍了LeetCode 28题"找出字符串中第一个匹配项的下标"的两种解法:暴力匹配和KMP算法。暴力匹配通过逐个字符比较实现,时间复杂度O(m×n);KMP算法利用next数组跳过不必要匹配,时间复杂度O(m+n)。文章详细解释了KMP的核心思想,包括next数组的定义和构建过程,并提供了Python和Java代码实现。两种方法各具特点:暴力匹配简单直观,KMP更高效但实现复杂,适合处理长字符串匹配问题。

2603_95532426的博客 225

关于字符串【力扣151.反转字符串中的单词的思考】

【摘要】本文介绍了字符串反转问题的解决方案。通过三个关键步骤实现:首先去除多余空格,然后整体反转字符串,最后逐个反转单词。方法强调函数封装思想,将不同功能模块化处理。注意事项指出需特别关注函数封装在代码复用和维护中的重要性,这种分步处理方法能有效提高代码可读性和执行效率。

wasb666的博客 258

LeetCode 55. 跳跃游戏

这道跳跃游戏问题要求判断能否从数组起点跳到终点。解题关键在于维护当前可达的最远下标maxReach:遍历数组时,若当前位置i超过maxReach则失败;否则用i+nums[i]更新maxReach。例如[2,3,1,1,4]可达,而[3,2,1,0,4]不可达。贪心算法只需O(n)时间和O(1)空间,通过不断扩展可达范围来判断终点是否可达,而无需考虑具体跳跃路径。核心步骤是先检查当前位置是否可达,再更新maxReach。

zander258的博客 182

leetcode 104二叉树的最大深度

为根的树深度是 1。

qq_63176310的博客 228

算法札记:利用floyd判环算法优化SPFA判负环算法

本文提出了一种优化SPFA算法检测负环的方法,使用Floyd判环算法替代传统的DFS判环。作者在SPFA中增加了计时器和Floyd判环(龟兔赛跑算法),当步数超过2n时启动判环检查。代码实现中,cycle()函数实现了Floyd判环逻辑,通过比较慢指针和快指针来检测环的存在。经测试,该优化在Acwing平台上比朴素SPFA快50倍,比基于栈的优化版本快1.2-1.4倍。这种方法显著提高了负环检测效率,尤其适用于大规模图论问题。

Keven_11的博客 246

vray1.5 for 3dmax 2009中文版

vray1.5 for 3dmax 2009中文破解版

上一篇: 代码随想录算法训练营第21天 | 第六章 二叉树part08
下一篇: 代码随想录算法训练营第23天 | 第七章 回溯算法part02
monoki
博客等级 码龄7年 251粉丝 · 42原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值