首页 > 其他分享 >Day14 二叉树Part2 递归的应用(二叉树相关)

Day14 二叉树Part2 递归的应用(二叉树相关)

时间:2024-07-30 11:50:54浏览次数:15  
标签:return 递归 self Day14 Part2 二叉树 root 节点

任务

226. 翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

思路

逻辑上,我们知道用递归遍历一棵树,一定会遍历每个节点。因此在遍历的过程中处理即可。

  • 考虑递归基,即当节点为空时直接返回。
  • 考虑单层递归,为了反转二叉树,如何处理当前节点呢?即如何反转以当前节点为根的二叉树呢? 交换其左右子节点,然后分别以左右孩子节点为根去反转(递归处理孩子节点)。

实际上这里的思路我们使用正好使用了类似先序遍历的流程,先处理当前节点的局部,再递归处理其孩子节点;实际上,如果在这里采用后序遍历的思路,也即是先让孩子节点为根去反转,再将自己的左右孩子反转。

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root: return root
        tmp = root.left
        root.left = root.right
        root.right = tmp
        
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root

特别地,如果采用中序遍历,先以左孩子为根去反转,再交换左右孩子,此时就需要再以左孩子为根去反转了(因为此时左孩子已经是之前的右孩子了)

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root: return root
        self.invertTree(root.left)
        tmp = root.left
        root.left = root.right
        root.right = tmp
        self.invertTree(root.left)
        return root

实际上个人认为不用太区分树的遍历用递归时用的是什么序遍历,而是根据单次递归中需要的逻辑是什么去思考和编码即可,如果题目够复杂,你的遍历可能都不是单纯的处理一次,分不出先中后序。即处理时机可能在递归调用左右子节点的前中后多个部分。

101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

思路

看到这道题,想到要遍历两棵树的过程中,判断这两棵树是否是对称的。这道题的递归基和单次递归逻辑联系的更紧密一些

  • 如果这两棵树的树根均为空,则返回True
  • 如果这两树的树根不同时为空,则返回False
  • 如果这两树的树根均不为空,判断如下
    • 如果两树根值不等,则返回False
    • 如果两树根值相等,则判断它们的子树是否为对称(a的左子树是否和b的右子树对称,a的右子树是否和左子树对称),同时满足则返回True,否则返回False
class Solution:
    def isSymmetricTwoTree(self,root1,root2):
        if root1 and root2: 
            if root1.val != root2.val:
                return False
            else: # 值相等时,同时遍历两棵树的子树,确认是否对称
                case1 = self.isSymmetricTwoTree(root1.left,root2.right)
                case2 = self.isSymmetricTwoTree(root1.right,root2.left)
                return case1 and case2
        elif not root1 and not root2:
            return True
        # elif not root1 and root2 or (root1 and not root2):
        #     return False
        else: return False

    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        return self.isSymmetricTwoTree(root.left,root.right)

104.二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

思路

  • 递归基:当前节点为空时,返回0
  • 单层递归逻辑:当前节点的最大深度为,其左节点的最大深度和右节点最大深度中较大的加1.
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root: return 0
        leftNum = self.maxDepth(root.left)
        rightNum = self.maxDepth(root.right)
        return max(rightNum,leftNum) + 1

111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。

思路

大体思路和最大深度相同,但是直接将max改为min后,发现结果出错,一个只有右链的树返回的值是1,说明单层逻辑考虑的情况节点的左右孩子一边为空的时候按照之前的逻辑是不对的,因此需要特别处理,当某孩子一边为空,则返回另一孩子的最小深度。

class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        if not root: return 0
    
        leftNum = self.minDepth(root.left)
        rightNum = self. minDepth(root.right)
        if not root.left and root.right: return rightNum + 1
        elif root.left and not root.right: return leftNum + 1
        return min(rightNum,leftNum) + 1

注意这最后两道题,最大深度和最小深度,用之前的层序遍历也可以实现。

  • 最大深度用层序遍历的逻辑是,开始用res记录,每层加1,层序遍历完成后返回res
  • 最小深度用层序遍历的逻辑是,用res记录,同样每层加1,但是如果提前碰到叶子节点,则直接返回res加1。

也即是说,用dfs和bfs都可以实现这两个功能,目前在二叉树章节中的理解是,dfs是用递归的逻辑去思考(递归基,单层递归逻辑),bfs是用层序遍历逻辑处理,也就是用层序遍历的那个队列二重循环的模板去处理。

心得体会

对于这种递归的题目,思考如何解时不要陷入到整个流程运作的细节,而是思考这样两个问题:

  1. 为了让递归不无限下分,边界条件是什么?也就是,递归基是什么?有了归基,我们知道递归可以有终点,会一层一层的返回给上层递归函数(类比循环中的终止条件是什么),此外,这个相当于我们针对边界的处理,比如节点为空时我们的题意的逻辑是什么?
  2. 单层递归时,为了实现逻辑,我们该怎么做?(类比循环中的单次循环中我们该做什么) 这个相当于是如果当前节点不是边界,我们的题意的逻辑是什么。

标签:return,递归,self,Day14,Part2,二叉树,root,节点
From: https://www.cnblogs.com/haohaoscnblogs/p/18332060

相关文章

  • 算法笔记|Day11二叉树
    算法笔记|Day11二叉树☆☆☆☆☆leetcode144.二叉树的前序遍历题目分析代码☆☆☆☆☆leetcode94.二叉树的中序遍历题目分析代码☆☆☆☆☆leetcode145.二叉树的后序遍历题目分析代码☆☆☆☆☆leetcode102.二叉树的层序遍历题目分析代码☆☆☆☆☆leetcode107.......
  • LeetCode - #107 二叉树的层序遍历 II
    文章目录前言1.描述2.示例3.答案关于我们前言我们社区陆续会将顾毅(Netflix增长黑客,《iOS面试之道》作者,ACE职业健身教练。)的Swift算法题题解整理为文字版以方便大家学习与阅读。LeetCode算法到目前我们已经更新到105期,我们会保持更新时间和进度(周一、......
  • DAY13 二叉树part01
     今日任务 二叉树的递归遍历(前中后)二叉树的迭代遍历(前中后)二叉树的统一迭代遍历二叉树的层序遍历(共十道题目)完成情况递归已掌握,代码略迭代前中手写一编,后和统一未学习层序遍历题目如下102.二叉树的层序遍历1/**2*Definitionforabinarytreenode.3*s......
  • LeetCode LCR 124.推理二叉树(哈希表 + 建树)
    某二叉树的先序遍历结果记录于整数数组 preorder,它的中序遍历结果记录于整数数组 inorder。请根据 preorder 和 inorder 的提示构造出这棵二叉树并返回其根节点。注意:preorder 和 inorder 中均不含重复数字。示例1:输入:preorder=[3,9,20,15,7],inorder=......
  • Day13 二叉树Part1 遍历
    递归遍历要理解递归,可以借助二叉树的递归遍历来理解。下面是二叉树递归遍历,以这个为例,来阐述下递归的原理。#Definitionforabinarytreenode.#classTreeNode:#def__init__(self,val=0,left=None,right=None):#self.val=val#self.left=......
  • LeetCode654. 最大二叉树
    题目链接:https://leetcode.cn/problems/maximum-binary-tree/description/题目叙述给定一个不重复的整数数组nums。最大二叉树可以用下面的算法从nums递归地构建:创建一个根节点,其值为nums中的最大值。递归地在最大值左边的子数组前缀上构建左子树。递归地在最大......
  • 数据结构-二叉树、堆、图
    一、线索二叉树规律:在有n个节点的链式二叉树中必定存在n+1个空指针链式二叉树中有很多的空指针,可以让这些空指针指向前一个节点\后一个节点,从而在有序遍历(中序遍历)二叉树时,不需要使用递归而通过循环即可以完成,并且效率要比递归快得多一定是搜索二叉树线索二叉树的结构typ......
  • LeetCode222.完全二叉树的节点个数
    题目链接:https://leetcode.cn/problems/count-complete-tree-nodes/description/题目叙述给你一棵完全二叉树的根节点root,求出该树的节点个数。完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该......
  • 数据结构——链式二叉树(C语言版)
    链式二叉树的结构⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。通常的⽅法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别⽤来给出该结点左孩⼦和右孩⼦所在的链结点的存储地址。                                ......
  • (leetcode学习)236. 二叉树的最近公共祖先
    给定一个二叉树,找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树T的两个节点p、q,最近公共祖先表示为一个节点x,满足x是p、q的祖先且x的深度尽可能大(一个节点也可以是它自己的祖先)。”示例1:输入:root=[3,5,1,6,2,0,8,nul......