前言
本日带大家举行二叉树的实战篇2,学会并相识二叉树属性,无论什么要求深度,还是路径,求和等等,一文带大家弄懂。本文用于纪录自己的学习过程,同时向大家举行分享相关的内容。本文内容参考于代码随想录同时包含了自己的许多学习思索过程,如果有错误的地方接待批评指正!
对称二叉树
101. 对称二叉树 - 力扣(LeetCode)
相关本领:首先来看题意哈,我们是要关于root节点轴对称,什么意思呢,就是镜像对称,左边的外面等于右边的外面,左边的里面等于右边的里面,就是这个意思,不符合这个条件的就是非对称了。那这道题怎么解呢?我们用递归的方式来解。还记得之前说过的递归三要素嘛,没啥事,不记得也行,如今带大家回首并实战。
- 确定递归的参数和返回值:很显着看这道题,我们需要做什么,是比较根节点的两个左右子树是否是翻转的,当然具体比较的就是二者的值了,以是我们传入的参数肯定就是两个节点,需要返回的就是二者的比较结果,以是返回值就是True 或者False
- 确定递归的制止条件:什么时候制止,这里来看,当符合对称树的情况是不是就一种,两个节点均为空即为制止条件,但是不符合对称树的情况呢?要么左边空右边非空,要么左边非空右边空,要么两者均不为空,但是两者的值不相等,也不属于对称树。
- 确定单层递归的逻辑:在确定还没到达递归制止的条件的时候就是单层递归的逻辑了,处理的情况就是二者均不为空且值相等。怎么处理,我们需要比较的是外部(左节点的左孩子,右节点的右孩子),内部(左节点的右孩子,右节点的左孩子),如果都对称就返回true,有任何一侧不对称返回false
故实当代码为:
- # Definition for a binary tree node.
- # class TreeNode:
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution:
- def isSymmetric(self, root: Optional[TreeNode]) -> bool:
- if not root:
- return True
- return self.campare(root.left,root.right)
- def campare(self,left,right):
- if left == None and right != None : return False
- elif left != None and right == None : return False
- elif left == None and right == None : return True
- elif left.val != right.val : return False
- outside = self.campare(left.left,right.right)
- inside = self.campare(left.right,right.left)
- issame = outside and inside
- return issame
复制代码 二叉树的最大深度
104. 二叉树的最大深度 - 力扣(LeetCode)
相关本领:看到这道题是不是有点熟悉,我们之前讲层序遍历的时候学习过,只不外那是层序遍历的迭代方法求解的,这下我们来看看如何使用递归的方法解这道题。求深度高度这种是不是就是只要左右子树的深度的最大值加1就是当前节点的深度高度了,那么递归下去是不是就可以求出根节点的深度了。同样的我们来看递归三要素:
- 确定递归的参数和返回值:来看这道题,我们需要做什么,是当前节点的深度,就是其左右子节点的深度最大值加1即可,为什么加1,要加上本身这一层。那我们左右子节点深度怎么求,是不是也是以左右子节点为根节点求深度,那就很显着了,递归的参数不就是其左节点或者右节点嘛,返回值当然就是深度了。
- 确定递归的制止条件:什么时候制止,这里来看,当节点为空返回零就行了,表示高度为0。
- 确定单层递归的逻辑:单层递归的逻辑就是很简单的,我们求其左节点的深度,在求其右节点的深度,取最大的加1就行了,就是当前节点的深度了。
- class Solution:
- def maxdepth(self, root: treenode) -> int:
- return self.getdepth(root)
-
- def getdepth(self, node):
- if not node:
- return 0
- leftheight = self.getdepth(node.left) #左
- rightheight = self.getdepth(node.right) #右
- height = 1 + max(leftheight, rightheight) #中
- return height
复制代码 二叉树的最小深度
111. 二叉树的最小深度 - 力扣(LeetCode)
相关本领:这道题同样很熟悉,也是我们之前讲层序遍历的时候学习过的,这下我们来看看如何使用递归的方法解这道题。求深度高度这种是不是就是只要左右子树的深度的最大值加1就是当前节点的深度高度了,那么递归下去是不是就可以求出根节点的深度了,不外这道题有点差别哦,我们要求的是最小深度。同样的我们来看递归三要素:
- 确定递归的参数和返回值:跟求最大深度的处理方式是雷同的,我们传入的参数就是节点,返回数值即高度。
- 确定递归的制止条件:什么时候制止,这里来看,当节点为空返回零就行了,表示高度为0。
- 确定单层递归的逻辑:单层递归的逻辑这里就与求最大深度差别了,我们要看我们是要找最近的叶子节点的深度,那么如果按照之前的直接改成求min来做会出现错误,当没有左子树有右子树的时候就会返回零,但是其不是叶子节点就会发生歧义。以是我们这里处理就是无左节点,有右节点的时候返回右边的最小,同样的无右节点,有左节点的时候返回左边的最小即可
- class Solution:
- def getDepth(self, node):
- if node is None:
- return 0
- leftDepth = self.getDepth(node.left) # 左
- rightDepth = self.getDepth(node.right) # 右
-
- # 当一个左子树为空,右不为空,这时并不是最低点
- if node.left is None and node.right is not None:
- return 1 + rightDepth
-
- # 当一个右子树为空,左不为空,这时并不是最低点
- if node.left is not None and node.right is None:
- return 1 + leftDepth
-
- result = 1 + min(leftDepth, rightDepth)
- return result
- def minDepth(self, root):
- return self.getDepth(root)
复制代码 完全二叉树的节点个数
222. 完全二叉树的节点个数 - 力扣(LeetCode)
相关本领:这道题还是比较简单的,我们直接看就行,实在其做法与求最大深度是很像的,就是左子树的节点个数加上右节点的节点个数就行了:
- 确定递归的参数和返回值:传入节点,求节点个数,返回数值,节点的个数。
- 确定递归的制止条件:什么时候制止,这里来看,当节点为空返回零就行了,表示节点个数为0。
- 确定单层递归的逻辑:单层递归的逻辑就是我们求左子树的节点个数加右节点的节点个数,两者相加再加1,加上自己本身的一个节点,就是当前的节点个数了。
- # Definition for a binary tree node.
- # class TreeNode:
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution:
- def countNodes(self, root: Optional[TreeNode]) -> int:
- if not root:
- return 0
- leftnums=self.countNodes(root.left)
- rightnums=self.countNodes(root.right)
- nums=leftnums+rightnums+1
- return nums
复制代码 平衡二叉树
110. 平衡二叉树 - 力扣(LeetCode)
相关本领:首先我们的明确平衡二叉树的定义是什么,即其左右子树的高度差不能大于1。那么我们就能明确我们需要去做些什么了。找出左子树的高度和右子树的高度二者做差取绝对值即可。
- 确定递归的参数和返回值:按照我们需要去做的,传入的参数就是其左右子节点,返回值即两者的高度。
- 确定递归的制止条件:什么时候制止,这里来看,当节点为空返回零就行了,表示高度为0。
- 确定单层递归的逻辑:我们找出左子树的高度和右子树的高度,当差的绝对值大于1即不符合定义返回-1,或者其左子树和右子树已经有不满意定义的情况直接返回-1,符合条件就返回高度即可。
- # Definition for a binary tree node.
- # class TreeNode:
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution:
- def isBalanced(self, root: Optional[TreeNode]) -> bool:
- return self.get_hight(root) != -1
- def get_hight(self, node):
- if not node:
- return 0
- left = self.get_hight(node.left)
- right = self.get_hight(node.right)
- if left == -1 or right == -1 or abs(left - right) > 1:
- return -1
- return max(left, right) + 1
复制代码 二叉树的全部路径
257. 二叉树的全部路径 - 力扣(LeetCode)
相关本领:找出路径,就是我们要一直到达叶子节点才行,那么这里我们会用到回溯的思想。由于我们会有变量来保存路径,当达到叶子节点输出该路径后,我们需要从路径中回溯上个节点的情况,要否则下个叶子节点的输出会带上这个叶子节点,这就是有问题的了。
- 确定递归的参数和返回值:我们需要当前的节点,一个保存路径的path,一个保存结果的result。返回值这里有没有都行,由于我们已经用result来保存结果了。
- 确定递归的制止条件:当到达叶子节点就可以制止了,即其节点左右子节点为空。
- 确定单层递归的逻辑:当左右节点存在就进入,同时这里要留意结束递归后要紧跟回溯,回溯是跟递归一一对应的。
- # Definition for a binary tree node.
- # class TreeNode:
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution:
- def traversal(self, cur, path, result):
- path.append(cur.val)
- if cur.left == None and cur.right == None:
- sPath='->'.join(map(str,path))
- result.append(sPath)
- if cur.left:
- self.traversal(cur.left,path,result)
- path.pop()
- if cur.right:
- self.traversal(cur.right,path,result)
- path.pop()
- def binaryTreePaths(self, root):
- result = []
- path = []
- if not root:
- return result
- self.traversal(root, path, result)
- return result
复制代码 左叶子之和
404. 左叶子之和 - 力扣(LeetCode)
- 相关本领:这里的难点就是我们该怎么去判断是不是左叶子节点,留意是左叶子节点,而不是左节点。判断其是不是左叶子节点,我们需要通过其父节点才可以大概来判断
- 确定递归的参数和返回值:递归的参数就是节点,由于我们需要去判断是不是左叶子节点。返回值就是其左叶子节点的值
- 确定递归的制止条件:当节点为空,或者其左右子节点为空就可制止,由于我们得通过父节点来判断,以是到这就可制止了。
- 确定单层递归的逻辑:我们需要判断其左节点是不是叶子节点,是就保留其值举行累加,右子树同样的操作,只判断其是否有左叶子节点。
- # Definition for a binary tree node.
- # class TreeNode:
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution:
- def sumOfLeftLeaves(self, root):
- if root is None:
- return 0
- if root.left is None and root.right is None:
- return 0
-
- leftValue = self.sumOfLeftLeaves(root.left) # 左
- if root.left and not root.left.left and not root.left.right: # 左子树是左叶子的情况
- leftValue = root.left.val
-
- rightValue = self.sumOfLeftLeaves(root.right) # 右
- sum_val = leftValue + rightValue # 中
- return sum_val
复制代码 找树左下角的值
513. 找树左下角的值 - 力扣(LeetCode)
相关本领:我们要找左下角的值,看清题目是左下角,并不是我们一直找左节点就行了的,也同样可能会在右子树的左节点的,以是我们观察其特性,其一定会出如今最深的一层的叶子节点中,以是我们就可以来解题目了。
- 确定递归的参数和返回值:传入的就是节点和深度,通过最深的一层的叶子节点来判断,返回值就是其节点的值
- 确定递归的制止条件:当到达叶子节点就可以制止了。
- 确定单层递归的逻辑:左节点存在就进入直到叶子节点,同样的留意递归结束后,我们的深度需要回溯到其本来的值即减一即可,由于我们还要去右节点中举行寻找。
- # Definition for a binary tree node.
- # class TreeNode:
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution:
- def findBottomLeftValue(self, root: TreeNode) -> int:
- self.max_depth = float('-inf')
- self.result = None
- self.traversal(root, 0)
- return self.result
-
- def traversal(self, node, depth):
- if not node.left and not node.right:
- if depth > self.max_depth:
- self.max_depth = depth
- self.result = node.val
- return
-
- if node.left:
- depth += 1
- self.traversal(node.left, depth)
- depth -= 1
- if node.right:
- depth += 1
- self.traversal(node.right, depth)
- depth -= 1
复制代码 路径总和
112. 路径总和 - 力扣(LeetCode)
相关本领:练习过前面的题目后这道题就比较简单了,直接来看递归三要素
- 确定递归的参数和返回值:递归的参数就是节点,以及我们用来纪录值的count,返回值就是存在与否即true或者false
- 确定递归的制止条件:当count为0的时候而且到达了叶子节点即返回true,或者达到叶子节点count并未为0即返回false
- 确定单层递归的逻辑:左节点存在就进入,count减去当前值,递归结束后要加回来,即回溯的过程。
- # Definition for a binary tree node.
- # class TreeNode:
- # def __init__(self, val=0, left=None, right=None):
- # self.val = val
- # self.left = left
- # self.right = right
- class Solution:
- def traversal(self, cur: TreeNode, count: int) -> bool:
- if not cur.left and not cur.right and count == 0: # 遇到叶子节点,并且计数为0
- return True
- if not cur.left and not cur.right: # 遇到叶子节点直接返回
- return False
-
- if cur.left: # 左
- count -= cur.left.val
- if self.traversal(cur.left, count): # 递归,处理节点
- return True
- count += cur.left.val # 回溯,撤销处理结果
-
- if cur.right: # 右
- count -= cur.right.val
- if self.traversal(cur.right, count): # 递归,处理节点
- return True
- count += cur.right.val # 回溯,撤销处理结果
-
- return False
-
- def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
- if root is None:
- return False
- return self.traversal(root, targetSum - root.val)
复制代码 算法基础系列
一文相识什么是数组及其经典考察题目
走进链表及其经典考察题目
还不知道什么是哈希表,看这篇文章就够了
字符串匹配究极大招【KMP】:带你一步步从原理到构建
【栈与队列】:基础实战篇-CSDN博客
【双指针法】:这么常用的你怎么能不知道-CSDN博客
【二叉树】理论基础篇1-CSDN博客
【二叉树】实战篇1-CSDN博客
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |