【算法篇】三道题理解什么是递归,回溯和剪枝

news2024/12/23 0:12:53

递归,回溯,剪枝

        想必大家再学习算法知识的路上经常听到回溯,剪枝类似的概念,对于初学者来说,很容易把他们理解成一种新的算法思想,其实回溯和剪枝只是在递归的基础上稍加修改,对于解决某些特定问题非常有帮助,我从力扣上选了三道题,我会粘贴题目链接,并对每道题进行详细的原理分析,希望大家能坚持看完,绝对能有收获,大家有更好的思路也欢迎大家在评论区交流啊!

 

文章顺序:

题目链接=》算法原理=》代码呈现

思想总结:

回溯:从⼀个初始状态开始,按照⼀定的规则向前搜索,当搜索到某个状态⽆法前进时,回退到前⼀个状态,再按照其他的规则搜索。回溯算法在搜索过程中维护⼀个状态树,通过遍历状态树来实现对所有可能解的搜索。

剪枝:如在二叉树中搜索某数时,通过在递归函数执行之前加一层条件判断的方式判断是否已经找到要找的数了,如果找到了便可以不用进入下面的递归函数,以此实现节省时间和空间的目的。

1. 二叉树剪枝

题目链接:

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

算法思路:

        如果我们选择从上往下删除,我们需要收集左右⼦树的信息,这可能导致代码编写相对困难。然⽽,通过观察我们可以发现,如果我们先删除最底部的叶⼦节点,然后再处理删除后的节点,最终的结果并不会受到影响。
        因此,我们可以采⽤后序遍历的⽅式来解决这个问题。在后序遍历中,我们先处理左⼦树,然后处理右⼦树,最后再处理当前节点。在处理当前节点时,我们可以判断其是否为叶⼦节点且其值是否为 0,如果满⾜条件,我们可以删除当前节点。
  • 需要注意的是,在删除叶⼦节点时,其⽗节点很可能会成为新的叶⼦节点。因此,在处理完⼦节点后,我们仍然需要处理当前节点。这也是为什么选择后序遍历的原因(后序遍历⾸先遍历到的⼀定是叶⼦节点)。
  • 通过使⽤后序遍历,我们可以逐步删除叶⼦节点,并且保证删除后的节点仍然满⾜删除操作的要求。这样,我们可以较为⽅便地实现删除操作,⽽不会影响最终的结果。
  • 若在处理结束后所有叶⼦节点的值均为 1,则所有⼦树均包含 1,此时可以返回。

代码呈现:

class Solution {
    public TreeNode pruneTree(TreeNode root) {
       return dfs(root);
    }
    private TreeNode dfs(TreeNode root){
        if(root==null){return root;}
        if(root.left==null&&root.right==null){
            if(root.val==0){
                return null;
            }else{
                return root;
            }
        }
        TreeNode left=dfs(root.left);
        TreeNode right=dfs(root.right);
        root.left=left;
        root.right=right;
        if(left==null&&right==null&&root.val==0){
            root=null;
        }
        return root;
    }
}

2.二叉搜索树中第k小的元素

题目链接: 

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

算法思路:

算法流程:
定义⼀个全局的变量 count,在主函数中初始化为 k 的值(不⽤全局也可以,当成参数传⼊递归过程中)。
递归函数的设计:int dfs(TreeNode* root): (返回值为第 k 个结点)。
递归函数流程(中序遍历):
1.递归出⼝:空节点直接返回 -1,说明没有找到;
2.去左⼦树上查找结果,记为 retleft:
  • 如果 retleft == -1,说明没找到,继续执⾏下⾯逻辑;
  • 如果 retleft != -1,说明找到了,直接返回结果,⽆需执⾏下⾯代码(剪枝);
3.如果左⼦树没找到,判断当前结点是否符合:
  • 如果符合,直接返回结果
4.如果当前结点不符合,去右⼦树上寻找结果。

代码呈现:

class Solution {
    int ret;
    int n;
    public int kthSmallest(TreeNode root, int k) {
       n=k;
       return dfs(root);   
    }
    private int dfs(TreeNode root){
        if(n==0) return ret;
        if(root.left==null&&root.right==null){
            if(n!=0)
            {n--;
            ret=root.val;
            }return ret;
        } 
       if(root.left!=null) dfs(root.left);
       if(n!=0){n--;
       ret=root.val;
       }if(n==0) return ret;
       if(root.right!=null) dfs(root.right);
       return ret;
    }
}

3.二叉树的所有路径

题目链接:

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

算法思路:

使⽤深度优先遍历(DFS)求解。
路径以字符串形式存储,从根节点开始遍历,每次遍历时将当前节点的值加⼊到路径中,如果该节点为叶⼦节点,将路径存储到结果中。否则,将 "->" 加⼊到路径中并递归遍历该节点的左右子树。
定义⼀个结果数组,进⾏递归。递归具体实现⽅法如下:
  1. 如果当前节点不为空,就将当前节点的值加⼊路径 path 中,否则直接返回;
  2. 判断当前节点是否为叶⼦节点,如果是,则将当前路径加⼊到所有路径的存储数组 paths 中;
  3. 否则,将当前节点值加上 "->" 作为路径的分隔符,继续递归遍历当前节点的左右⼦节点。
  4. 返回结果数组。
特别地,我们可以只使⽤⼀个字符串存储每个状态的字符串,在递归回溯的过程中,需要将路径中的当前节点移除,以回到上⼀个节点。
具体实现⽅法如下:
  1. 定义⼀个结果数组和⼀个路径数组。
  2. 从根节点开始递归,递归函数的参数为当前节点、结果数组和路径数组。                                      
    a. 如果当前节点为空,返回。
    b. 将当前节点的值加⼊到路径数组中。
    c. 如果当前节点为叶⼦节点,将路径数组中的所有元素拼接成字符串,并将该字符串存储到结果数组中。
    d. 递归遍历当前节点的左⼦树。
    e. 递归遍历当前节点的右⼦树。
    f. 回溯,将路径数组中的最后⼀个元素移除,以返回到上⼀个节点。
  3. 返回结果数组。

代码呈现:

class Solution {
    List<String> ret=new ArrayList<>();
    public List<String> binaryTreePaths(TreeNode root) {
      String path="";
      dfs(root,path);
      return ret;
    }
    private void dfs(TreeNode root,String path){
       if(root.left==null&&root.right==null){
        path+=""+root.val;
        ret.add(path);
        return;
       }
       path+=root.val+"->";
       if(root.left!=null){
        dfs(root.left,path);
       }
       if(root.right!=null) dfs(root.right,path);
       return;
    }    
}

❤️😍😍😍😍😍😍😍😍😍😍😍😍😍😍😍😍😍

🍔我是小皮侠,谢谢大家都能看到这里!!

🦚主页已更新Java基础内容,数据结构基础,数据库,算法,Redis相关内容。

🚕未来会更新Java项目,SpringBoot,docker,mq,微服务以及各种Java路线会用到的技术。

🎃求点赞!求收藏!求评论!求关注!

🤷‍♀️谢谢大家!!!!!!!!

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

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

相关文章

k8s的pod的管理

常用的Pod基础命令 列出所有命名空间中的所有Pod kubectl get pods --all-namespaces 列出指定命名空间中的所有Pod kubectl get pods -n <namespace> 显示指定Pod的详细信息&#xff0c;包括状态、事件等 kubectl describe pod <pod-name> -n <namespace>…

机器学习入门(一)

一、机器学习概述 1、人工智能 像人一样智能的综合与分析&#xff0c;机器模拟人类。 是一个系统&#xff0c;像人那样思考&#xff0c;像人那样理性思考。 是一个系统&#xff0c;像人那样活动&#xff0c;像人那样合理的系统 2、机器学习 让机器自动学习&#xff0c;而不…

SAP将假脱机(Spool requests)内容转换为PDF文档[RSTXPDFT4]

将假脱机(Spool requests)内容转换为PDF文档[RSTXPDFT4] 有时需要将Spool中的内容导出成PDF文件&#xff0c;sap提供了一个标准程序RSTXPDFT4可以实现此功能。 1, Tcode:SP01, 进入spool requests list 2, SE38 运行程序RSTXPDFT4 输入spool reqeust号码18680&#xff0c;然后…

excel 单元格嵌入图片

1.图片右键,设置图片格式 2.属性 随单元格改为位置和大小 这样的话&#xff0c;图片就会嵌入到单元格&#xff0c;也会跟着单元格的大小而改变

10-记录器

这个功能允许记录和重现以前的模拟。所有发生的事件都记录在记录器文件 recorder file中。 1 记录 所有数据仅在服务器端以二进制文件的形式写入。但是&#xff0c;记录器是使用 carla.Client管理的。 注意&#xff1a;在回放结束时&#xff0c;车辆将被设置为自动驾驶&#xf…

强化学习和QLearning及GAN到底是什么关系啊

强化学习&#xff08;Reinforcement Learning&#xff09;、Q-Learning 和生成对抗网络&#xff08;GANs&#xff09;是机器学习中的三个不同概念&#xff0c;它们虽然有一些交叉&#xff0c;但本质上是针对不同问题的技术方法。下面我来详细解释它们之间的关系和区别&#xff…

leetcode每日一题day22(24.10.2)——准时到达的列车最小时速

思路&#xff1a;这种在有约束条件情况下&#xff0c;求最值或最符合要求的情况&#xff0c;首先是很容易想到&#xff0c;从时速为1开始往后找找到满足条件就输出&#xff0c;但这无疑工程量很大&#xff0c;每种可能的速度都要对列车数组进行遍历&#xff0c; 时间复杂度为C…

链表Set_LinkList(并集)

并集是把两个集合合并&#xff0c;去除重复元素后组成的集合。 通过键盘输入将两个集合保存在链表A和链表B中&#xff0c;再创建一个链表C用于保存集合A、B的并集&#xff0c;将链表C打印输出。 提示&#xff1a; 1.相对于上一题&#xff08;链表Set_LinkList&#xff08;建立&…

java 微服务 端口冲突 redis虚拟磁盘满 nacos挂

java 微服务 端口冲突 哥 排除法呀 什么卸载软件QAQ netstat -ano | findstr :48080 输这个呀 然后 taskkill /PID 1234 /F redis虚拟磁盘满 导致 假死 挂了 nacos 挂了重启 nacosrun.bat startup -m standalone

facebook受众选择设置策略的最佳方式

在进行Facebookguanggao投放时&#xff0c;受众的选择是一个至关重要的步骤。正确的受众选择不仅能够帮助我们更好地定位目标用户&#xff0c;还能显著提高guanggao的转化率和投资回报率&#xff08;ROI&#xff09;。然而&#xff0c;受众选择的数量和范围同样是需要认真考虑的…

QtDesign预览的效果与程序运行的结果不一致的解决方法

存在的问题 使用Qt designer软件设计出来的界面&#xff0c;与转换成python程序运行出来的结果不一致&#xff0c;具体看下图 Qt designer预览结果 程序运行出来的结果 原因分析 我自己的电脑是2560*1600分辨率的屏幕&#xff0c;采用的是200%的缩放比例&#xff0c;出现这种…

虚拟机没有网络怎么解决

CentOS7为例 进入虚拟网络编辑器 1.更改设置 2.选中NAT模式点击3点击移除网络 4添加网络&#xff0c;随便选一个 5.点开NAT设置&#xff0c;记住网关 6.DHCP设置&#xff0c;注意虚拟机设置ip必须在起始ip和结束ip范围内 进入虚拟机网络适配器&#xff0c;自定义选中第4步操作…

Tailwind Css的使用

1.Tailwind Css是什么 官网解释&#xff1a;Tailwind CSS 的工作原理是扫描所有 HTML 文件、JavaScript 组件以及任何 模板中的 CSS 类&#xff08;class&#xff09;名&#xff0c;然后生成相应的样式代码并写入 到一个静态 CSS 文件中。 我的理解是利用Tailwind CSS 提供的…

Element-快速入门

什么是 Element 在现代前端开发中&#xff0c;组件化的思想日益盛行&#xff0c;Element组件库作为一款流行的UI组件库&#xff0c;特别适用于基于Vue.js的项目&#xff0c;它为开发者提供了丰富的组件和良好的开发体验。 想要使用Element的组件库&#xff0c;我们需要完成下面…

基于opencv的人脸闭眼识别疲劳监测

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色…

基于函数计算FC 部署 ComfyUI实现AI生图 的优势

基于函数计算FC 部署 ComfyUI实现AI生图 的优势 部署ComfyUI实现AI生图使用函数计算FC 一键部署ComfyUI 绘画平台的优势有哪些&#xff1f; 在文章开始之前&#xff0c;先来看一下基于函数计算FC 部署 ComfyUI实现AI生图 的大概步骤&#xff0c;整个基础部署操作比较简单。即便…

《Programming from the Ground Up》阅读笔记:p181-p216

《Programming from the Ground Up》学习第10天&#xff0c;p181-p216总结&#xff0c;总计34页。 一、技术总结 第10章主要讲计算机是如何计算的&#xff0c;如十进制、二进制、八进制、十六进制以及浮点数和负数的表示。属于比较基础的内容&#xff0c;如果有一定基础&…

ai免费写论文是原创吗?分享5款ai写作免费一键生成助手

在当今的学术研究和写作领域&#xff0c;AI技术的应用越来越广泛&#xff0c;尤其是在论文写作方面。许多AI写作工具声称能够一键生成高质量的论文&#xff0c;并且保证原创性。然而&#xff0c;这些工具是否真的能生成完全原创的论文&#xff0c;仍然是一个值得探讨的问题。 …

【函数】4.函数的单调性

本节课没有笔记示例&#xff0c;自己做好笔记&#xff01; 复合函数的单调性 最值 没讲 提醒我

【引领未来办公新风尚 —— 搭贝臻选,您的全能企业管理神器】

在这个瞬息万变的商业时代&#xff0c;每一分效率的提升都可能是超越竞争的关键。搭贝低代码平台匠心打造的“搭贝臻选”应用&#xff0c;集CRM营销管理、销售管理、采购管理、库存管理、财务管理、工单管理、人事管理及办公OA于一体&#xff0c;全方位赋能您的企业&#xff0c…