算法模板-对称性递归
简介
很多二叉树的题其实都可以通过递归来解决,这些以递归解决二叉树这种对称数据结构的策略,称为对称性递归(symmetric recursion)。
对称性递归
对称性递归,指的是对一个对称的数据结构(典型的是二叉树)从整体对称性思考,将大问题分解为多个小问题,即同时考虑对称的两部分而不是先解决一部分。
不过,可以通过对称性递归解决的问题主要是判断性问题,也就是返回值为bool型的,这种求解类型比较适合递归函数的调用(单值传递)。这类题目一般有两种情况,一种是单树问题,一种是双树问题。前者不需要用到子树的某一部分(如根节点左子树的右子树),只需要利用根节点左右子树的对称性即可进行递归;后者则是题目本身要求比较两棵树,需要两棵树进行判断。
解题模板
二叉树对称性递归的解题模板如下,分为递归边界和返回值两部分。
1.首先是递归边界,也就是特殊情况的判断。
若是单树问题,那么一般如下判断。
if not root: return True/False
if not root.left: return True/False/递归函数调用
if not root.right: return True/False/递归函数调用
若是双树问题,那么一般如下判断。
if not p and not q: return True/False
if not p or not q return True/False
当然,有时候也需要加上节点值的判断。
2.然后就是返回值,通常对称性递归的返回值是多个判断条件组成的复合语句,通常是下面集中判断的组合。
- 节点非空的判断
- 节点值比较的判断
- (单树)调用根节点左右子树的递归函数的判断
- (双树)调用两颗树的左右子树的递归函数的判断
题目列表
下面是力扣主站题库里可以通过上述解法解题的题目目录。
- leetcode-100 相同的树
- leetcode-104 二叉树的最大深度
- leetcode-110 平衡二叉树
- leetcode-226 翻转二叉树
- leetcode-543 二叉树的直径
- leetcode-572 另一棵树的子树
- leetcode-617 合并二叉树
- leetcode-965 单值二叉树
题解列表
100-相同的树
原题链接
这道题要求判断两棵二叉树是否相同。
边界情况:两棵树都是空树那么必然相同;
返回值:两棵树都非空、根节点值相等、左子树相同、右子树相同。
Python代码如下。
class Solution:def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:if not p and not q:return Truereturn bool((p and q) and (p.val == q.val) and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right))
104-二叉树的最大深度
原题链接
这道题要求求一棵二叉树的最大深度。
边界情况:空树的最大深度为0;
返回值:若树非空,则最大深度为左子树最大深度和右子树最大深度的较大者加上1。
Python代码如下。
class Solution:def maxDepth(self, root: Optional[TreeNode]) -> int:if not root:return 0else:return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
110-平衡二叉树
原题链接
这道题要求判断一棵树是不是平衡二叉树(任一节点左右子树高度差不超过1)。
边界情况:空树是平衡二叉树;
返回值:根的左右子树高度差不大于1、左右子树均是平衡二叉树。
Python代码如下,计算树深度的代码同上一题。
class Solution:def isBalanced(self, root: TreeNode) -> bool:def height(root):if not root:return 0else:return max(height(root.left), height(root.right)) + 1if not root:return Trueelse:return abs(height(root.left) - height(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)
226-翻转二叉树
原题链接
这道题要求将一棵二叉树镜像翻转。
边界情况:空树的翻转是本身;
返回值:翻转左子树后替换右子树,翻转右子树替换左子树。
Python代码如下。
class Solution:def invertTree(self, root: TreeNode) -> TreeNode:if not root:return Noneelse:root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)return root
543-二叉树的直径
原题链接
这题要求一棵二叉树的直径。(一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。)
边界情况:空树的最大深度为0;
返回值:若树非空,则最大深度为左子树最大深度和右子树最大深度的较大者加上1。
一棵树的直径就是对每个节点进行判断,找到以该节点为起点向左右子树走经过的节点数,记为dnode=l+r+1d_{node} = l + r + 1dnode=l+r+1。所有节点中最大的dnoded_{node}dnode减去1即为直径。
Python代码如下。
class Solution:def diameterOfBinaryTree(self, root: TreeNode) -> int:self.rst = 0def depth(root):if not root:return 0else:l, r = depth(root.left), depth(root.right)self.rst = max(l + r + 1, self.rst)return max(l, r) + 1depth(root)return self.rst - 1
572-另一棵树的子树
原题链接
这道题要求判断另一棵树是不是一棵树的子树。
边界情况:若两树中有一者为空则不会存在子树;
返回值:若两棵树不为空,先判断是不是同一棵树,同一棵树就返回True;接着判断一棵树的左子树是否是另一棵树或者一棵树的右子树是否是另一棵树的子树。
Python代码如下,这里求解是否同一棵树用到了之前的代码。
class Solution:def isSubtree(self, root: TreeNode, subRoot: TreeNode) -> bool:def isSameTree(p, q):if not p and not q:return Truereturn bool((p and q) and (p.val == q.val) and isSameTree(p.left, q.left) and isSameTree(p.right, q.right))if not root or not subRoot:return Falseif isSameTree(root, subRoot):return Truereturn self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)
617-合并二叉树
原题链接
这题要求合并两个二叉树,对应位置数值相加。
边界情况:两棵树都为空则返回空树;其中任意一棵树为空,返回另一棵树。
返回值:两棵树都不空,则合并后的树节点值为两棵树节点值相加,合并后的左子树为两树的左子树合并的结果,右子树也类似。
Python代码如下。
class Solution:def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:if not root1:return root2if not root2:return root1if root1 and root2:root1.val = root1.val + root2.valroot1.left = self.mergeTrees(root1.left, root2.left)root1.right = self.mergeTrees(root1.right, root2.right)return root1
965-单值二叉树
原题链接
这道题要求判断一棵树是不是单值二叉树(每个节点值相同)。
边界情况:空树肯定是单值二叉树;如果左子树非空且左子树根节点值和当前节点值不等则返回False,右子树类似;
返回值:左子树是单值二叉树且右子树也是单值二叉树。
Python代码如下。
class Solution:def isUnivalTree(self, root: TreeNode) -> bool:if not root:return Trueif (root.left and root.left.val != root.val) or (root.right and root.right.val != root.val):return Falsereturn self.isUnivalTree(root.left) and self.isUnivalTree(root.right)
补充说明
本文启发自一篇力扣题解,简单以力扣主站题库为例介绍了比较简约的对称性递归在实际解题的使用条件和使用方法。
算法模板-对称性递归相关推荐
- 常用算法模板(递归、分治、贪心、动态规划、回溯)
一.递归算法 递归算法:是指一种通过重复将问题分节为同类的子问题而解决问题的方法.它能解决的问题有①数据的定义是按递归定义的,如斐波拉契数:②问题解法按递归算法实现,如汉诺塔问题:③数据的结构形式是按 ...
- 九十五、二叉树的递归和非递归的遍历算法模板
@Author:Runsen 刷Leetcode,需要知道一定的算法模板,本次先总结下二叉树的递归和非递归的遍历算法模板. 二叉树的四种遍历方式,前中后加上层序遍历.对于二叉树的前中后层序遍历,每种遍 ...
- 算法模板-广度优先遍历
本文转载自Maple博客的算法模板-01背包问题,转载请注明出处. 简介 广度优先遍历(Breadth-First-Search,BFS),其特点便体现在广度,它是按"层"&quo ...
- 计算机考研数据结构算法模板
计算机考研数据结构算法模板 前言 临近考研,想给考研党们分享一些比较通用的算法模板,让复习更高效一点.如果备考时间足够长,备考人应该有大量时间刷大量习题,会有自己总结的算法模板,笔者文章参考了王道考研 ...
- kuangbin 最小生成树专题 - ZOJ - 1586 QS Network (朴素 Prim算法 模板题)
kuangbin 最小生成树专题 - ZOJ - 1586 QS Network (朴素 Prim算法 模板题) 总题单 week 3 [kuangbin带你飞] 题单 最小生成树 + 线段树 Cli ...
- 算法模板:归并排序【沈七】
本文已收录于专栏 ⭐️ <算法通关笔记>⭐️ 算法模版:归并排序 前言 基本概念 算法思想 常用模板 完结散花 参考文献 前言 唤我沈七就好. 往期专栏: 算法模板:快速排序 基本概念 归 ...
- 力扣刷题-python-回溯算法-1(回溯算法模板、题型)
文章目录 1.回溯算法 2.回溯算法模板 3.回溯实例(77.216.17.39.40.131.93.78.90.491.46.47) 4.总结 1.回溯算法 回溯算法的本质就是穷举,最多再加上剪枝, ...
- ACM算法模板总结(分类详细版)
本文模均引用于y总的算法模板,网址:AcWing (转载请注明出处,本文属于持续更新ing.......biubiubiu......) 本人码风比起y总真的差远了,所以敲一遍后,还是想把y总的搬上来 ...
- 匈牙利算法和hopcroft_karp算法模板
今晚学习了hopcroft_karp算法,留个模板,顺便也留个匈牙利算法模板. 题目为POJ 1469,在本题中,两种算法所用时间基本一致 //hopcroft_karp算法,复杂度O(sqrt(n) ...
最新文章
- codeforce 603B - Moodular Arithmetic
- Could not read from remote repository
- (BAE)jetty8+struts2导致 welcome-file-list 失效
- Increasing or Decreasing 序列 转换
- 机器学习中val_小波变换(七):小波变换在机器学习中的应用(下)
- spring框架如何调用异步方法?快进来学学吧
- 交互设计的114条原则
- 满足条件的数累加(信息学奥赛一本通-T1066)
- 【资源下载】921页《用Python3带你从小白入门机器学习实战》教程手册
- java.servlet不存在_eclipse提示servlet不存在 的解决办法
- spring之基本介绍以及老版本框架的下载地址
- 小米路由器 R1D 可用 java JRE openjdk
- CDRX6启动失败 提示尝试重新启动计算机和应用程序的解决方法
- wap 横屏适配和竖屏适配的通用方案
- 成功解决无法写入输出文件,此实现不是Windows平台FIPS验证加密算法的一部分
- 寒江独钓Windows内核编程-双机调试1
- 程序设计思维与实践 Month3 模拟
- 服装ERP系统的优势与缺点
- 计算机用word做海报,如何用Word文档做出一张简单的海报!
- 企业如何建立完善的管理体系