需要借助遍历的题型

题目一:翻转二叉树


思路:前中后序都可以
注意:中序遍历特别注意:在遍历左子树的时候,是传root.left的,因为,你上一步交换了左右指针,看代码一下就明白了
代码:

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public TreeNode invertTree(TreeNode root) {//每个结点的左右孩子反转就可以:中序遍历不行(改进的话:遍历右子树时候,传入的应该是左指针指向的孩子,因为上一步把左右指针交换了)if(root==null) return root;invertTree(root.left);swapChildren(root);//左右指针交换了,所以下面传明面上的left,实质上的right//要传root,不能传引用,否则它会变成孩子invertTree(root.left);return root;}public void swapChildren(TreeNode root){TreeNode temp=root.left;root.left=root.right;root.right=temp;}
}

题目二:对称二叉树


思想:
看左右子树,左边的4和右边的4,左边的3和右边的3,
结论:
左子树的left孩子和右子树的right孩子相等
左子树的right孩子和右子树的left孩子相等
所以左右子树一起遍历,不过关系要对应:
left.left和right.right
left.right和right.left
代码

class Solution {public boolean isSymmetric(TreeNode root) {if(root==null) return true;return  compare(root.left,root.right);}    //比较的左右子树的内外两侧,所以一起遍历public boolean compare(TreeNode left,TreeNode right){//镜像对比//baseif(left==null&&right==null) return true;if(left==null&&right!=null) return false;if(left!=null&&right==null) return false;//两个结点是否对称(不能省略...后面的是比较他们的子树是否对称)if(left.val!=right.val) return false;//子树是否对称boolean leftCom=compare(left.left,right.right);boolean rightCom=compare(left.right,right.left);boolean isSame=leftCom&&rightCom;return  isSame;}
}

题目三:左叶子结点和(可以用变量,也可以用树形dp,它的本质就是遍历)

首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。

左叶子的明确定义:如果左节点不为空,且左节点没有左右孩子,那么这个节点的左节点就是左叶子

思路:
左子树的,右子树的左叶子之和加上本结点的左叶子和=总和
注意:这道题也是经典的类树形dp,但是类树形dp本质也是递归,只是把递归的信息封装到一个结构了,后面会写
我们先看遍历的代码

class Solution {public int sumOfLeftLeaves(TreeNode root) {//只有一个字段的info直接用变量代替//root的左结点不为null,且左结点的左右孩子是null,它就是左叶子if(root==null) return 0;int leftsum=sumOfLeftLeaves(root.left);int rightsum=sumOfLeftLeaves(root.right);//本结点的左叶子和等于孩子的加自己的int curleftsum=leftsum+rightsum;if(root.left!=null&&root.left.left==null&&root.left.right==null){curleftsum+=root.left.val;}return curleftsum;}
}

题目四:路径总和==target

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。

方法:
深度优先遍历记录总和和target比较,这里需要回溯

class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {//没有结点的情况下if(root==null) return false;//遍历:每遍历到一个节点就减targetSumtargetSum-=root.val;//分类各个情况if(root.left==null&&root.right==null) return targetSum==0;if(root.left!=null){boolean left=hasPathSum(root.left,targetSum);//不用回溯,这里是基本类型,不会影响targetSumif(left) return true;//不能直接return left因为下面的可能会可以}if(root.right!=null){boolean right=hasPathSum(root.right,targetSum);return right;}//左右都不能解决return false;}
}注意:这道题是经典的暴力递归回溯的问题,借助遍历去回溯

题目五:最大二叉树题


方法:
选中数组中最大的值,作文root,同时以此去分割左右数组,root.left让左数组去构建,root.right让右数组去构建,这是一个递归的过程

代码

class Solution {public TreeNode constructMaximumBinaryTree(int[] nums) {return process(nums,0,nums.length-1);}public TreeNode process(int[] nums,int left,int right){//base:边界情况考虑if(left>right) return null;if(left==right) return new TreeNode(nums[left]);//抓到最大值及其下标int max=nums[left];int maxIndex=left;for(int i=left+1;i<=right;i++){if(max<nums[i]){max=nums[i];maxIndex=i;}}TreeNode root=new TreeNode(max);//构建子树root.left=process(nums,left,maxIndex-1);root.right=process(nums,maxIndex+1,right);return root;}}

题目六:合并二叉树


方法:
这道和上道题目都是构建二叉树的题,但是它是基于前序遍历而来的,所以我们也可以理解所有的题目都是依据遍历性去做的
本题方法:同时遍历两棵树,如果都有的结点,我们返回他们的和,只有一棵树有的结点,我们返回该结点,没有结点,就是返回null,

代码

class Solution {public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {//递归合并....处理本层结点,递归其他层//baseif(root1==null) return root2;if(root2==null) return root1;//我们选择在一棵树上合并=====>同步遍历(PS:因为合并可能在我们的树上会发生结构变化,所以要连接好我们的结点)root1.val+=root2.val;root1.left=mergeTrees(root1.left,root2.left);root1.right=mergeTrees(root1.right,root2.right);return root1;}
}

遍历总结:基本上所有的题目都是依据遍历性的,但是有些时候,遍历的每层向上返回的东西太多了,比较麻烦处理,我们借助一个结构去返回,下面就是借助递归

借助递归返回多个信息的题型

题目一:二叉树的最大深度


方法:
这道题,其实返回的信息只有一个,但是我们以此作为模板
本题分析:
要想得root树的深度,左子树的最大深度+右子树的最大深度+1就是本结点为root的最大深度
所以,我们的需要从左右子树收集的信息就是height

信息结构

 public static class Info{int height;public Info(int height){this.height=height;}}

代码

public Info process(TreeNode root){if(root==null){return new Info(0);}Info leftInfo=process(root.left);//左树信息Info rightInfo=process(root.right);//右树信息int height=Math.max(leftInfo.height,rightInfo.height)+1;return new Info(height);}

题目二:二叉树的最小深度

思想:和上一题一样
不一样:这里需要考虑左右孩子是不是为null

public Info process(TreeNode root){//返回的height是最小值,所以默认可以设置它为最大值,但是,最后它还是最大值,因为着他是没有孩子的,所以最后要拦截最大值if(root==null){return new Info(0);}//没有孩子就是本身高度就是0,,有一个孩子就是那个孩子的高度+1Info leftInfo=process(root.left);Info rightInfo=process(root.right);int height=Integer.MAX_VALUE;//考虑各个情况if(root.left==null) height=rightInfo.height+1; if(root.right==null) height=leftInfo.height+1;if(root.left!=null&&root.right!=null) height=Math.min(leftInfo.height,rightInfo.height)+1;height=height==Integer.MAX_VALUE?1:height;return new Info(height);}

题目三:判断一棵树是不是平衡二叉树

方法:
平衡二叉树:左右子树都是平衡的,左右子树高度差的绝对值在1内
信息结构

 public  static class Info{boolean isBalanced;int height;public Info(boolean isBalanced, int height) {this.isBalanced = isBalanced;this.height = height;}}

代码

 public Info process(TreeNode root){//baseif(root==null){return new Info(true,0);}//加工本结点(需要用到它自己的子树信息)Info leftInfo=process(root.left);Info rightInfo=process(root.right);int height=Math.max(leftInfo.height,rightInfo.height)+1;boolean isBalanced=true;if(!leftInfo.isBalanced||!rightInfo.isBalanced||Math.abs(leftInfo.height-rightInfo.height)>1){isBalanced=false;}return new Info(isBalanced,height);}

题目四:判断一棵树是不是BST(搜索树)

分析结构
左右子树都是BST,本结点val>左子树的最大val,本结点val<右子树最小的val
信息结构

public static class Info{boolean isBalanced;int minVal;int maxVal;public Info(boolean isBalanced,int minVal,int maxVal){this.isBalanced=isBalanced;this.minVal=minVal;this.maxVal=maxVal;}}

代码

 public Info process(TreeNode root){if(root==null) return null;//最大值和最小值不好加工//所以得到的左右子树的信息可能是null;这里也要注意返回值的默认值Info leftInfo=process(root.left);Info rightInfo=process(root.right);//这里的默认值是为了兼容一个结点的时候,返回的默认值int minVal=root.val;int maxVal=root.val;boolean isBalanced=true;//它最后还要做额外的决策,所以单独开来if(leftInfo!=null){minVal=Math.min(minVal,leftInfo.minVal);maxVal=Math.max(maxVal,leftInfo.maxVal);}if(rightInfo!=null){minVal=Math.min(minVal,rightInfo.minVal);maxVal=Math.max(maxVal,rightInfo.maxVal);}//对于null的两种情况分开写if(leftInfo!=null&&!leftInfo.isBalanced) isBalanced=false;if(leftInfo!=null&&root.val<=leftInfo.maxVal) isBalanced=false;if(rightInfo!=null&&!rightInfo.isBalanced) isBalanced=false;if(rightInfo!=null&&root.val>=rightInfo.minVal) isBalanced=false;return new Info(isBalanced,minVal,maxVal);}

题目五:二叉树任意两结点的最近公共祖先


分析:
怎么找到最近公共祖先?
1:左子树有一个结点,右子树有一个结点,那么祖先就是本结点
2:本结点就是两结点中的一个结点,还有一个结点在子树上,本结点就是祖先
其他情况,祖先不在以本结点为root的树上
信息结构

 public static class Info{TreeNode ans;boolean findA;boolean findB;public Info(TreeNode ans,boolean findA,boolean findB){this.ans=ans;this.findA=findA;this.findB=findB;}}

代码

public Info process(TreeNode root, TreeNode A, TreeNode B){if(root==null) return new Info(null,false,false);Info leftInfo=process(root.left,A,B);Info rightInfo=process(root.right,A,B);boolean findA=leftInfo.findA||rightInfo.findA||A==root;boolean findB=leftInfo.findB||rightInfo.findB||B==root;TreeNode ans=null;if(leftInfo.ans!=null){ans=leftInfo.ans;}else if(rightInfo.ans!=null){ans=rightInfo.ans;}//还没有找到ansif(ans==null){//本结点找到了ans(子树各有一个||子树一个,自己一个||自己两个)if(findA&&findB) ans=root;}return new Info(ans,findA,findB);}

总结

二叉树题
先用递归返回多个信息的去想,如果就用遍历的代码去找和本题的联系

二叉树算法大总结:借助遍历的题型+需要借助递归返回多个信息的题型[本质:遍历]相关推荐

  1. 不怕面试被问了!二叉树算法大盘点

    作者 | BoCong-Deng 题图 | 视觉中国 出品 | CSDN博客 树结构对于程序员来说应该不陌生,特别是二叉树,基本只要接触算法这一类的都一定会碰到的,所以我打算通过一篇文章,对二叉树结构 ...

  2. 不怕面试被问了!二叉树算法大盘点 | 原力计划

    作者 | BoCong-Deng 责编 | 伍杏玲 头图 | CSDN 下载自视觉中国 出品 | CSDN博客 树结构对于程序员来说应该不陌生,特别是二叉树,基本只要接触算法这一类的都一定会碰到的,所 ...

  3. 二叉树为空意味着二叉树_不怕面试被问了!二叉树算法大盘点

    作者 | BoCong-Deng 题图 | 视觉中国 出品 | CSDN博客 树结构对于程序员来说应该不陌生,特别是二叉树,基本只要接触算法这一类的都一定会碰到的,所以我打算通过一篇文章,对二叉树结构 ...

  4. java二叉树合并_Java(树的前中后序遍历构造二叉树题型整合)前序和中序、中序和后序、前序和后序遍历序列构造二叉树算法整合归纳...

    前言 二叉树各种花里胡哨的算法题真的把我搞晕了,今天特地整理出一类有关二叉树的算法题,希望能帮助阅读到此文章的人,今后不再受此类题型的困扰. 一.题目类型 已知二叉树的两种遍历序列,请根据该序列构建二 ...

  5. 二叉树层序遍历 c语言,C语言按层次遍历二叉树算法

    下面是编程之家 jb51.cc 通过网络收集整理的代码片段. 编程之家小编现在分享给大家,也给大家做个参考. #define MaxSize 1000 typedef char ElemType; t ...

  6. 数据结构与算法之美笔记——基础篇(中):树,二叉树,二叉查找树,平衡二叉查找树,红黑树,递归树,堆

    树: A 节点就是 B 节点的父节点,B 节点是 A 节点的子节点.B.C.D 这三个节点的父节点是同一个节点,所以它们之间互称为兄弟节点.我们把没有父节点的节点叫作根节点,也就是图中的节点 E.我们 ...

  7. 数据结构 - 二叉树 - 面试中常见的二叉树算法题

    数据结构 - 二叉树 - 面试中常见的二叉树算法题 数据结构是面试中必定考查的知识点,面试者需要掌握几种经典的数据结构:线性表(数组.链表).栈与队列.树(二叉树.二叉查找树.平衡二叉树.红黑树).图 ...

  8. 大数据日知录_腾讯T4专家精心整理:java+大数据+机器学习+数据挖掘+算法大集结...

    前言 本篇文章总共八大部分组成,包括数据挖掘:概念.模型.方法和算法:大数据日知录:架构与算法:大数据算法:数据结构与算法经典问题解析:算法基础:打开算法之门:机器学习算法大集结:Java数据结构和算 ...

  9. 万字长文详解二叉树算法,再也不怕面试了!| 技术头条

    作者 | 人魔七七 责编 | 胡巍巍 树的基本概念篇 前言 由于我们后面讲的一些结构有很多是树结构实现的比如堆,然后基于堆可以实现优先级队列,有界优先级队列等,所以我们先讲述树结构,我们可能常见到的是 ...

最新文章

  1. (转)JS正则表达式元字符
  2. linux用户及用户组管理
  3. microsoft word中在公式后插入可交叉引用的公式编号
  4. 你所不知道的ASP.NET Core MVC/WebApi基础系列(二)
  5. 10年C#历程的MVP之路与MVP项目介绍
  6. TensorRT学习笔记5 - 运行fc_plugin_caffe_mnist
  7. Redis在生产中不得不重视的几个运维问题
  8. adf4350配置_配置MySQL以进行ADF开发
  9. 45万例患者基因检测显示:NGS很难检测出七分之一的致病变异
  10. selenium自动化案例(二)滑动验证码破解
  11. linux 快捷matlab_ubuntu下Matlab_Linux添加工具包操作步骤
  12. Unity3D之UGUI基础3:Image图片
  13. JAVAFX-1 开发应用
  14. vs2005打点不提示
  15. CCNA学习指南中文第七版-1
  16. Matlab里面如何实现多行注释
  17. 有关SOP封装的一些总结
  18. 黑帽SEO-网页劫持
  19. IDEA与VsCode两种开发工具的比较
  20. linux vi编辑器操作手册

热门文章

  1. 黑暗背景(所有暗主题cobalt,dracula...)Rstudio查看对象窗口viewer没有滚动条,白亮背景就有(所有白主题chrome,cloud)。R版本[64-bit] R-3.6.0
  2. 计算机专业本科毕业生去当兵,本科毕业去当兵如何?过来人是这么说的,很有道理!...
  3. 稳压二极管稳压电路如何设计
  4. NOI2019 游记
  5. Redis数据库常用操作命令(查询db、key、value)
  6. 新媒体运营胡耀文教程:创作爆款短视频的“编剧思维”
  7. 什么是ThreadLocal?ThreadLocal基本使用
  8. RAD Studio破解补丁合集(2018.12.25)
  9. 阿里云服务器实例忘记用户名密码
  10. opencv识别图像红色区域,并输出红色区域中心点坐标