当前位置: 首页 > news >正文

刷题日志(7)——二叉树高频习题(下)

文章目录

  • 一. 二叉树遍历的非递归实现
    • 1.先序非递归实现
    • 2.中序非递归实现
    • 3.后序非递归实现
  • 二、验证二叉树性质
    • 1.验证平衡二叉树
    • 2.验证二叉搜索树
    • 3.验证完全二叉树
  • 三. 完全二叉树的节点个数(时间复杂度低于O(n))

一. 二叉树遍历的非递归实现

1.先序非递归实现

//思路: 使用栈模拟递归过程
//      先序:  根 左  右 ,为了先打印左再打印右,则需要右节点先入栈
public static void preOrder(TreeNode root) {Stack<TreeNode> s=new Stack<>();s.add(root);while(!s.isEmpty()) {//对头出队列TreeNode cur=s.pop();System.out.print(cur.val+" ");//先入右,再入左if(cur.right!=null) {s.add(cur.right);}if(cur.left!=null) {s.add(cur.left);}}
}

2.中序非递归实现

在这里插入图片描述

public static void inOrder(TreeNode root) {if(root!=null) {Stack<TreeNode> s=new Stack<>();//只要栈不为空或者root不为空,就不停止while(!s.isEmpty()||root!=null) {//只要节点root存在左孩子,就一直遍历左孩子if(root!=null) {s.push(root);     //遍历过程加入栈中root=root.left;   //到下一个左孩子}//如果root为空,即此时左孩子为空,则处理中间节点对头else {TreeNode cur=s.pop();  //队头出队System.out.print(cur.val+" ");root=cur.right;        //处理右孩子,右孩子重复左孩子的逻辑}}}
}

3.后序非递归实现

在这里插入图片描述

public static void posOrder(TreeNode root) {if(root!=null) {Stack<TreeNode> stack=new Stack<>();Stack<TreeNode> collect=new Stack<>();stack.push(root);while(!stack.isEmpty()) {root=stack.pop();collect.push(root);if(root.left!=null) {stack.push(root.left);}if(root.right!=null) {stack.push(root.right);}	}while(!collect.isEmpty()) {System.out.print(collect.pop().val+" ");}}
}
//实际上一个栈也可以实现: https://www.bilibili.com/video/BV1194y16727

二、验证二叉树性质

1.验证平衡二叉树

//思路: 以二叉树的最大深为基础,设置标记位,表示是否为平衡二叉树,
//      递归求左右子树高度的同时计算高度差,只有abs(差值)>1就修改标记为,且只能true->false
//时间复杂度: O(n)
public class BlanceTree {
public static boolean blance;public int height(TreeNode root) {if(root==null) return 0;int lh=height(root.left); //左树高int rh=height(root.right);//右树高if(Math.abs(lh-rh)>1) {   //计算高度差blance=false;}return 1+Math.max(lh,rh);
}
public boolean isBalanced(TreeNode root) {blance=true;   //由于blance为静态成员,因此每次都要置为初始值height(root);return blance;
}

2.验证二叉搜索树

	//详细解释: https://www.bilibili.com/video/BV1194y16727public static long min,max; //记录当前树cur的最小,最大值public boolean isValidBST(TreeNode root) {if(root==null) {//这样设置为了避免空节点的影响,使lmax<val<rminmin=Long.MAX_VALUE;max=Long.MIN_VALUE;}boolean lok=isValidBST(root.left); //左子树是否为搜索树//拿到左子树的最大,最小值long lmin=min;long lmax=max;boolean rok=isValidBST(root.right);//右子树是否为搜索树//拿到右子树的最大最小值long rmin=min;long rmax=max;//更新全局最小,最大值min=Math.min(Math.min(lmin,rmin),root.val);  max=Math.max(Math.max(lmax,rmax),root.val);return lok&&rok&&lmax<root.val&&rmin>root.val;}

3.验证完全二叉树

在这里插入图片描述

//方法一: 节点编号
public static int MAXN=101;
public static TreeNode[] queue=new TreeNode[MAXN];
//记录节点编号的数组
public static int[] pos=new int[MAXN];
public static int l,r;//树的一个特性: 编号,知道1个编号就可以指定孩子的编号 =》 只要编号不连续就不是完全二叉树
public boolean isCompleteTree3(TreeNode root) {l=r=0;queue[r]=root;pos[r++]=1;int prevIndex=0;while(l<r) {TreeNode cur=queue[l];int index=pos[l++];if(index!=prevIndex+1) {return false;}prevIndex=index;if(cur.left!=null) {queue[r]=cur.left;pos[r++]=2*index;}if(cur.right!=null) {queue[r]=cur.right;pos[r++]=2*index+1;}}return true;
}//方法二:
//数组模型队列
public boolean isCompleteTree2(TreeNode root) {l=r=0;boolean leaf=false;queue[r++]=root;while(l<r) {TreeNode cur=queue[l++];//不是完全二叉树的情况://  1.左孩子为空,但右孩子不为空   2.左空右不空,后面节点一定要是叶子节点if((cur.left==null&&cur.right!=null)||(leaf&&(cur.left!=null||cur.right!=null))) {return false;}if(cur.left!=null) {queue[r++]=cur.left;}if(cur.right!=null) {queue[r++]=cur.right;}if(cur.left==null||cur.right==null) {leaf=true;}}return true;
}

三. 完全二叉树的节点个数(时间复杂度低于O(n))

在这里插入图片描述
在这里插入图片描述

	//给定节点,计算该节点到最底层的高度,设初始高度为1public static int mostLeft(TreeNode cur,int level) {while(cur!=null) {level++;cur=cur.left;}return level-1;}//cur: 当前节点//h: 整颗完全二叉树的高度,不是当前节点到底部的高度//level: 当前节点所在的高度//dfs2: 计算当前节点cur的节点个数public static int dfs2(TreeNode cur,int level,int h) {if(level==h) return 1;   //如果cur在最后一层,即叶子节点,显然节点数为1if(mostLeft(cur.right, level+1)==h) { return (1<<(h-level))+dfs2(cur.right,level+1,h); //再以右孩子为根,因此level+1}else {return (1<<(h-level-1))+dfs2(cur.left,level+1,h);//再以右孩子为根,因此level+1}}public int countNodes2(TreeNode root) {if(root==null) {return 0;}return dfs2(root,1,mostLeft(root, 1));}

参考于:视频链接

http://www.dtcms.com/a/314342.html

相关文章:

  • 高精度实战:YOLOv11交叉口目标行为全透视——轨迹追踪×热力图×滞留分析(附完整代码)
  • FrePrompter: Frequency self-prompt for all-in-one image restoration
  • Opencv[一]
  • R 语言科研绘图第 67 期 --- 箱线图-显著性
  • Spark SQL:用SQL玩转大数据
  • OpenCV轻松入门_面向python(第二章图像处理基础)
  • 论文阅读笔记:《Dataset Distillation by Matching Training Trajectories》
  • 【数据结构初阶】--算法复杂度详解
  • 登录弹窗,cv直接使用
  • 【FreeRTOS】系统时钟配置
  • HTTP基本结构
  • ICCV 2025|单视频生成动态4D场景!中科大微软突破4D生成瓶颈,动画效果炸裂来袭!
  • ICCV 2025|可灵团队新作 ReCamMaster:从单视频到多视角生成,多角度看好莱坞大片
  • socket与udp
  • 折叠屏网页布局挑战:响应式设计在工业平板与PC端的弹性适配策略
  • 【Mac】OrbStack:桌面端虚拟机配置与使用
  • LeetCode 140:单词拆分 II
  • 【MySQL03】:MySQL约束
  • mac 技巧
  • 零售消费行业研究系列报告
  • Java-基础-统计投票信息
  • Linux下载安装mysql,客户端(Navicat)连接Linux中的mysql
  • allegro建库--1
  • 【Redis】移动设备离线通知推送全流程实现:系统推送服务与Redis的协同应用
  • 模型学习系列之考试
  • 机器学习(8):线性回归
  • 基于落霞归雁思维框架的自动化测试实践与探索
  • OpenLayers 入门指南【五】:Map 容器
  • Unity发布Android平台实现网页打开应用并传参
  • 如何查看 iOS 电池与电耗:入门指南与实战工具推荐