算法学习记录:递归

news2025/4/2 2:48:56

        递归算法的关键在于回复现场,dfs()函数返回值、结束条件、它的作用。

        

目录

1.综合练习

2. 二叉树的深搜


1.综合练习

         39. 组合总和 - 力扣(LeetCode)

         关键在画出的决策树当中,前面使用过的2、3,后面的3、2,就不需要再次使用了,下次是从 i 位置开始继续向下进行递归操作。同时需要注意当 sum 的值超过 aim 的时候就需要结束循环条件。(因为刚做过就不画出详细的图片了)

class Solution {
public:
    int aim = 0;
    vector<vector<int>> ret;
    vector<int> path;
    unordered_map<int, vector<int>> hash();
    vector<vector<int>> combinationSum(vector<int>& candidates, int target)
    {
        aim = target;
        dfs(candidates, 0, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos, int sum)
    {
        if(aim == sum)
        {
            ret.push_back(path);
            return;
        }
        //如果是加的特别多了,就要向前进行返回
        if(sum > aim || pos >= nums.size())
        {
            return;
        }

        for(int i = pos; i < nums.size(); i++)
        {
            path.push_back(nums[i]);
            dfs(nums, i, sum += nums[i]);//递归到当前的位置继续进行选择,进行递归的是下一次的和,要不然返回来的时候
            sum -= nums[i];
            path.pop_back();
        }
    }
};

         494. 目标和 - 力扣(LeetCode)

       

        加 或者是 减有两种情况可以。注意最后的返回是 nums.size() == n 即可。

class Solution {
public:
    int cnt = 0,sum = 0,n = 0,_target = 0;
    int findTargetSumWays(vector<int>& nums, int target) 
    {
        //使用 dfs,进行暴力传递 nums,以及pos位置
        n = nums.size();
        _target = target;
        dfs(nums, 0);//从 0 位置开始进行递归 
        return cnt;
    }
    void dfs(vector<int>& nums, int pos)
    {
        if(nums.size() == pos)
        {
            if(sum == _target) cnt++;
            return ;
        }
        //进行分别进行选与不选的操作
        sum += nums[pos];

        dfs(nums, pos + 1);
        sum -= nums[pos];

        sum -= nums[pos];

        dfs(nums, pos + 1);
        sum += nums[pos];

    }

2. 二叉树的深搜

 2331. 计算布尔二叉树的值 - 力扣(LeetCode) 

       计算布尔值,知道左子树的布尔值,右子树的布尔值,以及此时根结点的布尔值,如此一来,这就是一个后续遍历二叉树。定义 dfs(TreeNode* root),返回值就是布尔值。关键在于以当前的位置为视角去判断左右子树。(由于是二次刷题,此处只展示核心代码部分).   

if(root->left == NULL && root->right == NULL) return root->val == 0 ? false : true;

        bool left = evaluateTree(root->left);
        bool right = evaluateTree(root->right);
        if(root->val == 2) 
        {
            return left | right;
        }
        else return left & right;

 206. 反转链表 - 力扣(LeetCode)

     

          这道题不是二叉树深搜的题目,是一道寻找子问题的题目,但是还是需要进行一次深度优先遍历dfs(ListNode* head),这个函数的操作就是将 head 以后的结点后进行翻转操作。

        子问题为:进行到当前的位置,如果是他的下一个位置不为 NULL,就需要将他下一个的下一个指向头位置.

if(head == NULL || head->next == NULL) return head;
        ListNode* Fhead = reverseList(head->next);
        head->next->next = head;
        head->next = NULL;
        return Fhead;

 129. 求根节点到叶节点数字之和 - 力扣(LeetCode)

        

        需要注意的是,在这个函数里面 ret 的不可定义为全局的变量,因为我们控制的 dfs 的意义为在当前位置的时候计算一下左右子树的和。其实每回进行的时候 ret 都要初始化为 0;

int sumNumbers(TreeNode* root) {
        //通过递归进行实现,现在一个函数已经无法满足
        return dfs(root, 0);
        //dfs 返回的是当前点加上 左右结点的和,还有另外一个函数表示的是到当前位置的时候此时前面的和
       
    }
    int dfs(TreeNode* root, int pernum)
    {
        int ret = 0;
        //dfs 表示从 0 开始向下进行遍历的求和
        pernum = pernum * 10 + root->val;
        if(root->left == NULL && root->right == NULL)
        {
            return pernum;
        }
        //相当于遍历到了最后的一个位置,然后计算左右子树的和
        if(root->left) ret += dfs(root->left, pernum);
        if(root->right) ret += dfs(root->right, pernum);
        return ret;
     }

 814. 二叉树剪枝 - 力扣(LeetCode)

        一看到这种题,就应当想到以当前位置结点,判断左子树,右子树的情况,如果是当前位置空直接返回,当前位置的左为空,右为空,同时 root->val == 0。我们就将当前位置变成 NULL;

TreeNode* pruneTree(TreeNode* root) {
        //通过分析判断得到,这个函数跟我想要的一样
        if(root == nullptr) return nullptr;

        //1.分别处理左右子树
        root->left = pruneTree(root->left);
        root->right = pruneTree(root->right);
        //处理完之后去处理一下根
        if(root->left == nullptr && root->right == nullptr && root->val == 0)
        {
            root = nullptr;
        }
        return root;
    }

98. 验证二叉搜索树 - 力扣(LeetCode)

        这道题需要使用 搜索二叉树的一个性质为:中序遍历完全符合升序的特点,如果是不符合就使用剪枝进行返回一个 false。dfs()表示以当前的位置为结点时候为二叉搜索树,返回值为 ture 或者是 false,递归出去的条件为:左右子树都为空的情况。

long prev = LONG_MIN;
if(root->left == NULL && root->right == NULL) return true;//一个结点肯定是二叉搜索树
        //需要判断左子树的 bool
        bool left = isValidBST(root->left);
        if(left == false) return false;
        //判断 根时候符合
        bool tmp = false;
        if(root->val > perv) tmp = true;
        perv = root->val;
        //进行剪枝
        if(tmp == false) return false;
        //判断右子树
        bool right = isValidBST(root->right);
        if(right == false) return false;
        if(right && left && tmp) return true;
        return false;//照顾编译器,防止最后出错

 230. 二叉搜索树中第 K 小的元素 - 力扣(LeetCode)

 dfs(TreeNode* root)就是进行遍历,当前结点为 NULL 的时候进行返回。需要定义全局变量 cnt 表示进行到了第几个,ret 表示最后的结果。每次判断根部的时候就cnt --;

class Solution {
public:
    //定义两个全局变量,一个表示还需要进行的次数,直到小于 0 为止,另外一个表示最后的结果
    // int cnt;
    // int ret;
    void dfs(TreeNode* root)
    {
        if(root == NULL || cnt == 0 ) return;
        dfs(root->left);
        cnt--;
        if(cnt == 0)
        {
            ret = root->val;
            return;
        } 
        dfs(root->right);
    }
    int kthSmallest(TreeNode* root, int k) {
        // cnt = k;
        // dfs(root);//通过深度优先遍历来修改ret的值
        // return ret;
        cnt = k;
        dfs(root);
        return ret;
    }
    int cnt = 0;
    int ret = 0;

257. 二叉树的所有路径 - 力扣(LeetCode)

        dfs(root, path),除了定义一个 root,还需要定义一个path,表示通过的路径。如果不在这里定义就需要将遍历一遍就进行复原。定义一个 path 会方便很多。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    //定义两个全局变量
    //string path;
    vector<string> ret;
    vector<string> binaryTreePaths(TreeNode* root) 
    {
      string path;
      dfs(root, path);
      return ret;
    }
    void dfs(TreeNode* root, string path)
    {
        path += to_string(root->val);
        if(root->left == NULL && root->right == NULL)
        {
            ret.push_back(path);
            return;
        }
        path.push_back('-');
        path.push_back('>');
        if(root->left) 
        {
            dfs(root->left, path);  
        }
        if(root->right)
        {
            dfs(root->right, path);
           
         }
    }
};

 46. 全排列 - 力扣(LeetCode)

        经典中的经典。

class Solution {
public:
    vector<vector<int>> ret;//表示最后结果
    vector<int> path;//走的路径
    bool used[8];//表示当前的数是否被使用了
    vector<vector<int>> permute(vector<int>& nums) {
        dfs(nums);//从 0 位置开始进行遍历
        return ret;
    }
    void dfs(vector<int>& nums)
    {
        if(path.size() == nums.size())
        {
            ret.push_back(path);
            return;
        }
        for(int i = 0; i < nums.size(); i++)
        {
            if(used[i] == false)
            {
                path.push_back(nums[i]);
                used[i] = true;

                dfs(nums);
                path.pop_back();
                used[i] = false;

            }
        }
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2325234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

可发1区的超级创新思路(python\matlab实现):MPTS+Lconv+注意力集成机制的Transformer时间序列模型

首先声明,该模型为原创!原创!原创!且该思路还未有成果发表,感兴趣的小伙伴可以借鉴! 应用场景 该模型主要用于时间序列数据预测问题,包含功率预测、电池寿命预测、电机故障检测等等。 一、模型整体架构(本文以光伏功率预测为例) 本模型由多尺度特征提取模块(MPTS)…

三、分类模块,通用组件顶部导航栏Navbar

1.封装通用组件顶部导航栏Navbar 不同效果 Component export struct MkNavbar {Prop title: string Prop leftIcon: ResourceStr $r("app.media.ic_public_left")ProprightIcon: ResourceStr $r("app.media.ic_public_more")PropshowLeftIcon: boolean…

PHY——LAN8720A 寄存器读写 (二)

文章目录 PHY——LAN8720A 寄存器读写 (二)工程配置引脚初始化代码以太网初始化代码PHY 接口实现LAN8720 接口实现PHY 接口测试 PHY——LAN8720A 寄存器读写 (二) 工程配置 这里以野火电子的 F429 开发板为例&#xff0c;配置以太网外设 这里有一点需要注意原理图 RMII_TXD0…

Flutter_学习记录_AppBar中取消leading的占位展示

将leading设置为null将automaticallyImplyLeading设置为false 看看automaticallyImplyLeading的说明&#xff1a; Controls whether we should try to imply the leading widget if null. If true and [AppBar.leading] is null, automatically try to deduce what the leading…

未来派几何风格包装徽标品牌海报标牌logo设计无衬线英文字体安装包 Myfonts – Trakya Sans Font Family

Trakya Sans 是一种具有几何风格的现代无衬线字体。Futura、Avant Garde 等。它具有现代条纹&#xff0c;这是宽度和高度协调的结果&#xff0c;尤其是在小写字母中&#xff0c;以支持易读性。 非常适合广告和包装、编辑和出版、徽标、品牌和创意产业、海报和广告牌、小文本、寻…

C语言深度解析:从零到系统级开发的完整指南

一、C语言的核心特性与优势 1. 高效性与直接硬件控制 C语言通过编译为机器码的特性&#xff0c;成为系统级开发的首选语言。例如&#xff0c;Linux内核通过C语言直接操作内存和硬件寄存器&#xff0c;实现高效进程调度。 关键点&#xff1a; malloc/free直接管理内存&#…

ctfshow WEB web8

首先确定注入点&#xff0c;输入以下payload使SQL恒成立 ?id-1/**/or/**/true 再输入一下payload 使SQL恒不成立 ?id-1/**/or/**/false 由于SQL恒不成立, 数据库查询不到任何数据, 从而导致页面空显示 由以上返回结果可知&#xff0c;该页面存在SQL注入&#xff0c;注入点…

【Linux】U-Boot 加载并启动 Linux 系统程序

U-Boot 加载并启动 Linux 系统程序 零、介绍 最近在玩一些嵌入式的开发板&#xff0c;在引导操作系统时需要用到U-Boot&#xff0c;故此研究一下。 U-Boot&#xff08;Universal Bootloader&#xff09;是一款开源的通用引导加载程序&#xff0c;专为嵌入式系统设计&#xff…

jarvisoj API调用 [JSON格式变XXE]

http://web.jarvisoj.com:9882/ 题目要求&#xff1a;请设法获得目标机器 /home/ctf/flag.txt 中的flag值 抓包得到&#xff1a; POST /api/v1.0/try HTTP/1.1 Host: web.jarvisoj.com:9882 Content-Length: 36 Accept-Language: zh-CN,zh;q0.9 User-Agent: Mozilla/5.0 (W…

机器学习的一百个概念(4)下采样

前言 本文隶属于专栏《机器学习的一百个概念》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…

NNI 适配 TensorRT10教程

引言 本文涉及两个框架及其版本分别为 NNI (Neural Network Intelligence) &#xff1a;3.0TensorRT&#xff1a;10.9.0.34 NNI 在文档 Speed Up Quantized Model with TensorRT里描述了如何使用 TensorRT 为NNI量化的模型实现加速&#xff0c;但是从NNI 的源代码https://gi…

多路径 TCP 调度的另一面

参考前面的文章 一个原教旨的多路径 TCP 和 MP-BBR 公平性推演&#xff0c;一直都破而不立&#xff0c;不能光说怎样不好&#xff0c;还得说说现状情况下&#xff0c;该如何是好。 如果 receiver 乱序重排的能力有限(拜 TCP 所赐)&#xff0c;如果非要在多路径上传输 TCP&…

vcpkg安装指定版本的库

一.vcpkg安装 使用git将vcpkg源码克隆到本地制定目录&#xff08;D:\vcpkg&#xff09;&#xff0c;并初始化 git clone https://github.com/microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh # Linux/macOS .\bootstrap-vcpkg.bat # Windows 如下图&#xff1a; 二.安…

【工具变量】上市公司供应链稳定性数据两个维度(2013-2023年)

供应链稳定性是指供应链在面对各种内外部因素的冲击和不确定性时&#xff0c;能够保持持续、顺畅运作的能力&#xff0c;而供应链稳定性指数是用于评估企业在其供应链管理中保持稳定性的一个重要指标。本分享数据参考钟涛&#xff08;2022&#xff09;、董浩和闫晴&#xff08;…

Redis场景问题2:缓存击穿

Redis 缓存击穿是指在缓存系统中&#xff0c;大量请求&#xff08;高并发访问&#xff09;同时访问一个不存在于缓存中&#xff08;一般是因为缓存过期或者数据未被加载到缓存&#xff09;但在数据库中存在的热点数据&#xff0c;从而导致这些请求直接穿透缓存层&#xff0c;涌…

RocketMQ - 从消息可靠传输谈高可用

先稍微介绍下RocketMQ架构。 主从架构 Broker 集群&#xff1a;每个 Broker 分为 Master 和 Slave 角色&#xff0c;Master 负责读写&#xff0c;Slave 作为热备。 同步复制&#xff08;SYNC_MASTER&#xff09;&#xff1a;消息写入 Master 后&#xff0c;需等待 Slave 同步完…

ES拼音分词自动补全实现

#测试拼音分词 POST /_analyze { "text":"如家酒店真不错", "analyzer": "pinyin" } #这里把拼音的首字母放到这里&#xff0c;也说明了这句话没有被分词&#xff0c;而是作为一个整体出现的 #还把每一个字都形成了一个拼音&#…

EFISH-SBC-RK3576 + 5G模组:无线工业相机与分布式AI质检‌

在智能制造与仓储物流场景中&#xff0c;传统有线工业相机存在部署成本高、灵活性差等痛点。‌eFish-SBC-RK3576‌ 通过 ‌5G无线传输 分布式NPU协同‌&#xff0c;实现跨产线、跨工厂的AI质检系统&#xff0c;检测效率提升300%&#xff0c;布线复杂度降低90%。 ‌1. 系统架构…

C/C++ 基础 - 回调函数

目录 前言 回调函数预备知识 函数指针 什么是函数指针 函数指针的语法 如何用函数指针调用函数 函数指针作为函数的参数 函数指针作为函数返回类型 函数指针数组 回调函数 什么是回调函数 为什么要用回调函数 怎么使用回调函数 总结 前言 在写项目的时候&#x…

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的消息队列:使用 RabbitMQ 实现异步处

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整…