【14】二叉树的Morris等

news2024/11/16 0:33:16

目录

一.树形dp套路 

二.派对的最大快乐值

三.Morris遍历

morris先序遍历

morris中序遍历

moris后序遍历

判断是不是搜索二叉树

四.额外习题


一.树形dp套路 

 

情况1:最大距离,节点X不参与。 => 左树最大距离 or 右树最大距离

情况2:最大距离,节点X参与。 => 最大距离 = 左树高度+1+右树高度

常见的分类,是头节点参不参与来罗列可能性。

可以设计:
节点的信息 => 最大距离maxDistance 、树高height

节点cur时的最大距离 = max{left的maxDistance, right的maxDistance,left的height+right的height+1}

	public static class Node { // 树节点
		public int value; // 节点值
		public Node left; // 左子树
		public Node right; // 右子树

		public Node(int data) { // 构造
			this.value = data;
		}
	}

    // 返回最大距离
	public static int maxDistance(Node head) { 
		return process(head).maxDistance;
	}
	

    // 一个节点的返回信息
	public static class ReturnType{
		public int maxDistance; // 最大距离
		public int h; // 高度
		
		public ReturnType(int m, int h) { // 构造
			this.maxDistance = m;; 
			this.h = h;
		}
	}
	
    // 给出当前节点的返回信息(最大距离,高度)
	public static ReturnType process(Node head) {
		if(head == null) {
			return new ReturnType(0,0);
		}
		ReturnType leftReturnType = process(head.left); // 左树返回信息
		ReturnType rightReturnType = process(head.right); // 右数返回信息
		int includeHeadDistance = leftReturnType.h + 1 + rightReturnType.h; // 计算包含根节点的最大距离
		int p1 = leftReturnType.maxDistance; // 左子树最大距离
		int p2 = rightReturnType.maxDistance; // 右子树最大举例
		int resultDistance = Math.max(Math.max(p1, p2), includeHeadDistance); // 到当前位置可以获得的最大距离
		int hitself  = Math.max(leftReturnType.h, leftReturnType.h) + 1; // 高度
		return new ReturnType(resultDistance, hitself); // 将信息放回给上一级
	}

二.派对的最大快乐值

情况1:节点X参与

X参与的最大快乐 = X乐 + a不来的最大快乐 + b不来的最大快乐 + c不来的最大快乐

情况2:节点X不参与

X不参与的最大快乐 = 0 + max(a来的最大快乐,a不来的最大快乐) + max(b来的最大快乐,b不来的最大快乐) + max(c来的最大快乐,c不来的最大快乐) 

	public static class Employee{
		public int happy;
		public List<Employee> nexts;
	}
	
	public static class ReturnType{
		public int no_maxhappy;
		public int yes_maxhappy;
		public ReturnType(int no, int yes) {
			no_maxhappy=no;
			yes_maxhappy=yes;
		}
	}
	
	public static ReturnType process(Employee head) {
		if(head.nexts.isEmpty()) { // 基层员工 
			return new ReturnType(0, head.happy);
		}
		int no_maxhappy=0; // head不来的最大快乐
		int yes_maxhappy=head.happy; // head来的最大快乐
		for(Employee next:head.nexts) {
			ReturnType node=process(next);
			yes_maxhappy+=node.no_maxhappy;
			no_maxhappy+=Math.max(node.no_maxhappy, node.yes_maxhappy);
		}
		return new ReturnType(no_maxhappy, yes_maxhappy);
	}

三.Morris遍历

笔试不要用Morris遍历,面试阶段用。(学术名词:线索二叉树)

【如果不用栈,如何回到上级节点,用底层节点大量的空闲指针】

标准1:如果没有左树 => 当前节点cur向右树走。

标准2

如果有左树,找到左树中最右节点 => 最右节点右指针为空 => 右指针指向当前节点cur => 当前节点cur向左树走。

标准3

如果有左树,找到左树中最右节点 => 最右节点右指针不为空 =>  当前节点cur向右树走。

	public static class Node {
		public int value;
		Node left;
		Node right;

		public Node(int data) {
			this.value = data;
		}
	}

	public static void morris(Node head) {
		if (head == null) {
			return;
		}
		Node cur1 = head;
		Node cur2 = null;
		while (cur1 != null) { //  过流程
			cur2 = cur1.left; // cur2是cur左孩子
			if (cur2 != null) {
				while (cur2.right != null && cur2.right != cur1) {
					cur2 = cur2.right;
				}
				// cur2变成cur左子树上,最后的节点
				if (cur2.right == null) { // 这是第一次来到cur
					cur2.right = cur1;
					cur1 = cur1.left;
					continue;
				} else { // cur2.right == null
					cur2.right = null;
				}
			}
			cur1 = cur1.right;
		}
	}

单独遍历左子树有边界这件事,每个节点至多被遍历1次,总代价至多是O(n),并不会多严重。

morris先序遍历

  • 只一次来到的节点 => 直接打印
  • 来到两次的节点 => 第一次打印
	public static void morrisPre(Node head) {
		if (head == null) {
			return;
		}
		Node cur1 = head;
		Node cur2 = null;
		while (cur1 != null) {
			cur2 = cur1.left;
			if (cur2 != null) {
				while (cur2.right != null && cur2.right != cur1) {
					cur2 = cur2.right;
				}
				if (cur2.right == null) {
					cur2.right = cur1;
					System.out.print(cur1.value + " ");
					cur1 = cur1.left;
					continue;
				} else {
					cur2.right = null;
				}
			} else {
				System.out.print(cur1.value + " ");
			}
			cur1 = cur1.right;
		}
		System.out.println();
	}

morris中序遍历

  • 只一次来到的节点 => 直接打印
  • 来到两次的节点 => 第二次打印
	public static void morrisIn(Node head) {
		if (head == null) {
			return;
		}
		Node cur1 = head;
		Node cur2 = null;
		while (cur1 != null) { //  过流程
			cur2 = cur1.left; // cur2是cur左孩子
			if (cur2 != null) {
				while (cur2.right != null && cur2.right != cur1) {
					cur2 = cur2.right;
				}
				// cur2变成cur左子树上,最后的节点
				if (cur2.right == null) { // 这是第一次来到cur
					cur2.right = cur1;
					cur1 = cur1.left;
					continue;
				} else { // cur2.right == null
					cur2.right = null;
				}
			}
			System.out.print(cur1.value + " ");
			cur1 = cur1.right;
		}
		System.out.println();
	}

moris后序遍历

	public static void morrisPos(Node head) {
		if (head == null) {
			return;
		}
		Node cur1 = head;
		Node cur2 = null;
		while (cur1 != null) {
			cur2 = cur1.left;
			if (cur2 != null) {
				while (cur2.right != null && cur2.right != cur1) {
					cur2 = cur2.right;
				}
				if (cur2.right == null) {
					cur2.right = cur1;
					cur1 = cur1.left;
					continue;
				} else {
					cur2.right = null;
					printEdge(cur1.left);
				}
			}
			cur1 = cur1.right;
		}
		printEdge(head);
		System.out.println();
	}

	public static void printEdge(Node head) {
		Node tail = reverseEdge(head);
		Node cur = tail;
		while (cur != null) {
			System.out.print(cur.value + " ");
			cur = cur.right;
		}
		reverseEdge(tail);
	}

	public static Node reverseEdge(Node from) {
		Node pre = null;
		Node next = null;
		while (from != null) {
			next = from.right;
			from.right = pre;
			pre = from;
			from = next;
		}
		return pre;
	}

判断是不是搜索二叉树

在中序遍历的位置判断,是否preValue是一直在递增的。

	public static boolean isBST(Node head) {
		if (head == null) {
			return true;
		}
		Node cur1 = head;
		Node cur2 = null;
		int preValue=Integer.MIN_VALUE;
		while (cur1 != null) { //  过流程
			cur2 = cur1.left; // cur2是cur左孩子
			if (cur2 != null) {
				while (cur2.right != null && cur2.right != cur1) {
					cur2 = cur2.right;
				}
				// cur2变成cur左子树上,最后的节点
				if (cur2.right == null) { // 这是第一次来到cur
					cur2.right = cur1;
					cur1 = cur1.left;
					continue;
				} else { // cur2.right == null
					cur2.right = null;
				}
			}
			if(cur1.value <= preValue) {
				return false;
			}
			preValue = cur1.value;
			cur1 = cur1.right;
		}
		return true;
	}

如果方法必须要节点第3次遍历的强整合

    => 递归套路是最优解(非叶子节点到3次,叶子节点到1次)

如果方法没必要节点第3次遍历的强整合

    => morris遍历(非叶子节点可以到2次,叶子到1次)

四.额外习题

原问题:

使用位图,2^32个数需要2^32bit的空间 = 512MB

进阶问题:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2041782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在 Spring Boot 的配置文件中使用环境变量?

1. 概述 在本教程中&#xff0c;我们将讨论如何在 Spring Boot 的application.properties和application.yml中使用环境变量。然后&#xff0c;我们将学习如何在代码中引用这些属性。 2. 在application.properties文件中使用环境变量 让我们定义一个名为JAVA_HOME的全局环境…

60行代码就可以训练/微调 Segment Anything 2 (SAM 2)

SAM2&#xff08;Segment Anything 2&#xff09;是Meta开发的一个新模型&#xff0c;可以对图像中的任何物体进行分割&#xff0c;而不局限于特定的类别或领域。这个模型的独特之处在于其训练数据的规模&#xff1a;1100万张图像和110亿个掩码。这种广泛的训练使SAM2成为训练新…

Linux内核分析(Linux中的进程)

文章目录 前言一、进程的概念1. 进程的概念2. 在内核中&#xff0c;进程叫做任务3. 进程的虚拟地址空间总结 二、进程的生命周期三、task_struct结构体分析三、进程的状态TASK_RUNNING (0)TASK_INTERRUPTIBLE (1)TASK_UNINTERRUPTIBLE (2)__TASK_STOPPED (4)__TASK_TRACED (8)E…

第十一章:特征选择与稀疏学习

1. 子集搜索与评价 “特征”&#xff1a;属性 “相关特征”&#xff1a;对当前学习任务有用的属性 “无关特征”&#xff1a;没什么用的属性&#xff0c;与当前的学习任务无关的属性 “特征选择”&#xff1a;从给定的特征集合中选择出相关特征子集的过程,&#xff08;数据…

海外公司注册推广:10个值得尝试的创新战略

在全球化和数字化时代&#xff0c;海外公司注册已成为一种重要趋势。许多企业意识到&#xff0c;将业务扩展到国外市场可以带来巨大的商机和竞争优势。面对不同的国家法规和市场环境&#xff0c;注册一家海外公司并将其推广并非易事。本文将介绍10个值得尝试的创新战略&#xf…

【Android 笔记】记移植OpenCV4.8图像人脸识别

前言 因业务需要&#xff0c;使用大屏端摄像头捕获图像&#xff0c;且要识别图像中人脸的数目以及从中随机抽取一人。 业务流程如下&#xff0c;调用摄像头预览、拍照&#xff0c;使用OpenCV库进行人脸识别&#xff0c;将识别到的人脸使用矩形框绘制出来&#xff0c;从识别的人…

Matlab绘制像素风字母颜色及透明度随机变化动画

本文是使用 Matlab 绘制像素风字母颜色及透明度随机变化动画的教程 实现效果 实现代码 如果需要更改为其他字母组合&#xff0c;在下面代码的基础上简单修改就可以使用。 步骤&#xff1a;(1) 定义字母形状&#xff1b;(2) 给出字母组合顺序&#xff1b;(3) 重新运行程序&#…

15年以来 — 战略性云平台服务的演进路径之全面呈现(含亚马逊、微软和谷歌)

Gartner每年都发布对全球IaaS平台进行评估的魔力象限报告。2023年底&#xff0c;Gartner将此项评估的名称改为“战略性云平台服务”&#xff08;Strategic cloud platform services&#xff09;&#xff0c;尽管其核心仍为IaaS&#xff0c;但是&#xff0c;毫无疑问&#xff0c…

【深度学习】什么是深度学习?

1. 前言 深度学习是机器学习的一个分支&#xff0c;它使用神经网络教计算机做人类自然而然会做的事情&#xff1a;从示例中学习。在深度学习中&#xff0c;模型会学习直接从图像、文本或声音等数据中执行分类或回归任务。深度学习模型可以达到最先进的准确率&#xff0c;通常超…

WPF自定义控件

控件模板 顾名思义就是在原有的控件上进行模版修改成自己需要的样式 把ProgressBar修改为一个水液面的进度条 <Window x:Class"XH.CustomLesson.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://s…

树莓派3B升级glibc-2.29

自从我树莓派的python升级到3.9&#xff0c;每次import numpy都会报错&#xff1a;libm.so.6: version GLIBC_2.29 not found。这又是怎么回事呢&#xff1f;查了资料才知道&#xff0c;原来是我的respbian系统版本低的原因&#xff08;如图&#xff09;。 &#xff08;可以用l…

Facebook广告投放优化思路分享,为何总是低量级

为什么谷歌优化总是不起效果&#xff1f;今天我来谈谈我的Facebook广告优化思路&#xff0c;希望对你有所帮助。感兴趣的可以点赞、收藏。关注我&#xff0c;每天分享海外推广知识。 以下是Facebook广告优化思路思维导图&#xff1a; 那么&#xff0c;今天主要来谈谈量级低的情…

哪个工具可以ai续写免费?多维度评测分享

在创意的征途中&#xff0c;你是否曾遇到过文思枯竭的困境&#xff1f;当灵感如同夜空中的流星&#xff0c;一闪而逝&#xff0c;如何捕捉并延续那份璀璨&#xff1f;答案或许就藏在ai续写软件的无限可能中。 不知道ai续写软件哪个好&#xff1f;别急&#xff0c;今天&#xff…

Win10 禁止更新-【延长更新时间】

文章目录 操作注册表 操作注册表 Win R regedit 打开注册表 粘贴&#xff1a; ** \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 代开目录 新建32位数据值 &#xff1a;FlightSettingsMaxPauseDays 999 然后到更新界面&#xff0c;就可以一直点

数字信号处理3:数字滤波器设计

文章目录 前言一、实验目的二、实验设备三、实验内容四、实验原理五、实验方法及要求1.用脉冲响应不变法设计巴特沃斯数字滤波器2. 用双线性变换法设计切比雪夫数字滤波器3. 用双线性变换法设计巴特沃斯数字滤波器,并将直接型结构转换成级联型结构4. 数字低通滤波器特性比较5…

GD - EmbeddedBuilder_v1.4.1.23782工程中的gdc名称必须和工程名称一致

文章目录 GD - EmbeddedBuilder_v1.4.1.23782工程中的gdc名称必须和工程名称一致概述笔记总结END GD - EmbeddedBuilder_v1.4.1.23782工程中的gdc名称必须和工程名称一致 概述 在看EmbeddedBuilder_v1.4.1.23782自带的demo工程。 看到 D:\EmbeddedBuilder_v1.4.1.23782\exam…

工业一体机立式报工台助力工厂改善生产报工效率

在现代化工业生产中&#xff0c;生产效率和管理水平是企业竞争力的关键。为了实现高效的生产管理&#xff0c;工厂需要一个可靠、稳定、便捷的报工系统。传统的报工方式存在诸多弊端&#xff0c;例如效率低、易出错、数据难以统计分析等。而工厂软件报工台立式工业一体机的出现…

家里浮毛怎么去掉最高效?这些宠物空气净化器总有一款适合你

我家是三个月大的时候被我领回家的。它简直就是个小天使&#xff0c;乖得不得了&#xff0c;既不乱尿也不掉毛。每次去朋友家&#xff0c;看到他们为猫咪掉毛头疼不已&#xff0c;我就忍不住在心里偷偷乐&#xff0c;觉得自己真是捡到了宝&#xff0c;怎么会有这么省心的猫咪呢…

上海知名泌尿外科专家常态化坐诊黄山新晨医院,让前列腺癌看得更早、更准!

继7月28日上海第四人民医院泌尿外科专家在黄山新晨医院开展义诊之后&#xff0c;8月9日和10日&#xff0c;该团队领头人周铁教授又完成了合作以来的首次坐诊&#xff0c;标志着双方合作从此进入常态化阶段。 周铁主任在查看患者的检查报告 周铁主任曾任中华医学会泌尿外科分会…

拍立淘API:商品ID与标题的快速获取

拍立淘&#xff08;Pailitao&#xff09;是阿里巴巴旗下的一个基于图像识别技术的购物应用功能&#xff0c;用户可以通过拍照或上传图片来快速找到相似的商品。然而&#xff0c;拍立淘本身并不直接提供一个公开的API接口供开发者使用来直接获取商品ID和标题等信息。 如果你想通…