二叉树题目:翻转二叉树以匹配前序遍历

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:翻转二叉树以匹配前序遍历

出处:971. 翻转二叉树以匹配前序遍历

难度

5 级

题目描述

要求

给定一个二叉树的根结点 root \texttt{root} root,二叉树中有 n \texttt{n} n 个结点,每个结点都有一个 1 \texttt{1} 1 n \texttt{n} n 之间的值且不同结点的值各不相同。另外给定一个由 n \texttt{n} n 个值组成的行程序列 voyage \texttt{voyage} voyage,表示预期的二叉树前序遍历结果。

通过交换结点的左右子树,可以翻转该二叉树中的任意结点。例如,翻转结点 1 \texttt{1} 1 的效果如下:

示例 0

请翻转最少的树中结点,使得二叉树的前序遍历与预期的遍历行程 voyage \texttt{voyage} voyage 相匹配

返回翻转的所有结点的值的列表。可以按任何顺序返回答案。如果不能,则返回列表 [-1] \texttt{[-1]} [-1]

示例

示例 1:

示例 1

输入: root = [1,2], voyage = [2,1] \texttt{root = [1,2], voyage = [2,1]} root = [1,2], voyage = [2,1]
输出: [-1] \texttt{[-1]} [-1]
解释:翻转结点无法令前序遍历匹配预期行程。

示例 2:

示例 2

输入: root = [1,2,3], voyage = [1,3,2] \texttt{root = [1,2,3], voyage = [1,3,2]} root = [1,2,3], voyage = [1,3,2]
输出: [1] \texttt{[1]} [1]
解释:翻转结点 1 \texttt{1} 1 交换结点 2 \texttt{2} 2 3 \texttt{3} 3,使得前序遍历可以匹配预期行程。

示例 3:

示例 3

输入: root = [1,2,3], voyage = [1,2,3] \texttt{root = [1,2,3], voyage = [1,2,3]} root = [1,2,3], voyage = [1,2,3]
输出: [] \texttt{[]} []
解释:前序遍历已经匹配预期行程,所以不需要翻转结点。

数据范围

  • 树中结点数目为 n \texttt{n} n
  • n = voyage.length \texttt{n} = \texttt{voyage.length} n=voyage.length
  • 1 ≤ n ≤ 100 \texttt{1} \le \texttt{n} \le \texttt{100} 1n100
  • 1 ≤ Node.val, voyage[i] ≤ n \texttt{1} \le \texttt{Node.val, voyage[i]} \le \texttt{n} 1Node.val, voyage[i]n
  • 树中的所有值各不相同
  • voyage \texttt{voyage} voyage 中的所有值各不相同

解法

思路和算法

二叉树的前序遍历的方法为:依次遍历根结点、左子树和右子树,对于左子树和右子树使用同样的方法遍历。对于每个结点,如果不翻转该结点,则遍历该结点之后依次遍历左子树和右子树,如果翻转该结点,则遍历该结点之后依次遍历右子树和左子树。由于题目要求翻转的结点数最少,因此只有当必须翻转结点的时候才翻转结点。当遍历到一个结点时,其子结点值和预期行程中的下一个值可能有以下情况。

  • 当前结点的左子结点为空或者左子结点值和预期行程中的下一个值相同,此时不需要翻转当前结点。

  • 当前结点的左子结点不为空且左子结点值和预期行程中的下一个值不同,如果不翻转当前结点则下一个访问的结点是左子结点,无法匹配预期行程,此时需要翻转当前结点。翻转当前结点之后不能保证匹配预期行程,而是需要访问原右子结点,判断当前结点的原右子结点值是否和预期行程中的下一个值相同,可能有以下两种情况。

    • 如果原右子结点值和预期行程中的下一个值相同,则翻转当前结点之后,原右子结点匹配预期行程,继续遍历判断其余的结点是否匹配预期行程。

    • 如果原右子结点值和预期行程中的下一个值不同,则翻转当前结点之后,仍无法匹配预期行程。由于当前结点无论是否翻转都无法匹配预期行程,因此无法通过翻转二叉树中的结点匹配预期行程。

根据上述分析,可以在二叉树前序遍历的基础上做修改,得到翻转的结点值列表。从根结点开始前序遍历二叉树,遍历过程中维护翻转的结点值列表并维护状态值记录是否存在翻转方案(不存在翻转方案表示无法通过翻转二叉树中的结点匹配预期行程),初始时翻转的结点值列表为空,状态值为存在翻转方案,具体做法如下。

  1. 如果当前结点为空或者状态值为不存在翻转方案,则直接返回。

  2. 如果当前结点值和预期行程中的当前值不同,则将翻转的结点值列表清空然后将 − 1 -1 1 加入翻转的结点值列表,并将状态值设为不存在翻转方案,然后返回。

  3. 根据当前结点的左右子结点,判断当前结点是否需要翻转,并决定遍历左右子树的顺序。

    • 如果当前结点的左子结点为空或者左子结点值和预期行程中的下一个值相同,则不需要翻转当前结点,依次对左子树和右子树前序遍历。

    • 否则,需要翻转当前结点,将当前结点值加入翻转的结点值列表,依次对右子树和左子树前序遍历。

遍历结束之后,即可得到翻转的结点值列表。如果存在翻转方案,则列表中的元素为所有需要翻转的结点值,特别地,当列表为空时,表示原二叉树已经匹配预期行程因此不需要翻转任何结点;如果不存在翻转方案,则列表中只有一个元素 − 1 -1 1

代码

class Solution {List<Integer> flips;int[] voyage;int n;int index;boolean possible;public List<Integer> flipMatchVoyage(TreeNode root, int[] voyage) {this.flips = new ArrayList<Integer>();this.voyage = voyage;this.n = voyage.length;this.index = 0;this.possible = true;preorder(root);return flips;}public void preorder(TreeNode node) {if (node == null || !possible) {return;}if (node.val != voyage[index]) {flips.clear();flips.add(-1);possible = false;return;}index++;TreeNode left = node.left, right = node.right;if (left == null || left.val == voyage[index]) {preorder(left);preorder(right);} else {flips.add(node.val);preorder(right);preorder(left);}}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是递归调用的栈空间,取决于二叉树的高度,最坏情况下二叉树的高度是 O ( n ) O(n) O(n)。注意返回值不计入空间复杂度。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装python第三方库后,在pycharm中不能正常导入

python小白学习opencv&#xff0c;使用pip安装完opencv库后import cv2报错&#xff0c;按照如下设置解决&#xff1a; 需要正确设置python解释器路径

⭐Unity 搭建UDP服务端(02)接收客户端消息

客户端在上一篇 由于服务器逻辑写的较为简单 所以直接上代码了~ using System; using System.Net; using System.Net.Sockets; using System.Text; using UnityEngine;public class UdpServer : MonoBehaviour {public static UdpServer instance;private void Awake(){if (…

如何选择靠谱的软件测试外包公司?CMA、CNAS软件测试报告获取

作为信息科技产业的代表之一&#xff0c;软件公司受到了越来越多的关注&#xff0c;它们的发展为我国的科技创新提供了强大的战略支撑。软件测试作为提升软件产品质量的后盾&#xff0c;日益成为一个专业化、标准化和规范化的行业&#xff0c;软件测试外包公司就是这种背景下成…

基于LSTM和N-gram序列的英文文本生成(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

IDEA中配置Git

Git 在IDEA中使用Git1 在IDEA中配置Git2 在IDEA中使用Git2.1在IDEA中创建工程并将工程添加至Git2.2 将文件添加到暂存区2.3 提交文件2.4 将代码推送到远程仓库2.5 从远程仓库克隆工程到本地2.6 从远程拉取代码2.7 版本对比2.8 创建分支2.9 切换分支2.10 分支合并 3 使用IDEA进行…

❀My学习Linux命令小记录(16)❀

目录 ❀My学习Linux命令小记录&#xff08;16&#xff09;❀ 61.who指令 62.sleep指令 63.kill指令 64.top指令 65.diff指令 ❀My学习Linux命令小记录&#xff08;16&#xff09;❀ 61.who指令 功能说明&#xff1a;显示目前登录系统的用户信息。 &#xff08;ps.who命…

如何搭建一套完整的智能安防视频监控平台?关于设备与软件选型的几点建议

安防视频监控系统主要由前端摄像机设备、视频显示设备、视频存储设备、安防应用软件/平台以及其它传输、辅助类设备组成。一般来说&#xff0c;安防监控系统具有可扩展和开放性&#xff0c;以方便未来的扩展和与其他系统的集成。今天我们就来介绍一下&#xff0c;搭建一套完整的…

Windows侧常见USB接口描述符综述

Windows侧常见USB接口描述符综述 1. 术语2. CDC类设备综述2.1. 概述2.2. CDC类Communications Interface描述符2.2.1. Header Functional Descriptor2.2.2. Union Functional Descriptor2.2.3. MBIM接口Class Functional Descriptors2.2.3.1. MBIM Functional Descriptor2.2.3.…

STM32使用SIM900A、SIM800C、SIM800A完成短信发送、连接onenet上传数据、拨打电话_完整教程

一、前言 本篇文章介绍SIM800C 、SIM800A、SIM900A 等等系列的模块的常用AT指令,讲解模块的使用方法,演示短信发送、拨打电话、网络连接,与服务器通信等常用案例。 如果只是用到发送短信、拨打电话、连接网络通信、这些模块的AT指令是兼容的。 文章最后贴了完整的STM32代码…

深度学习实战66-基于计算机视觉的自动驾驶技术,利用YOLOP模型实现车辆区域检测框、可行驶区域和车道线分割图

大家好,我是微学AI,今天给大家介绍一下深度学习实战66-基于计算机视觉的自动驾驶技术,利用YOLOP模型实现车辆区域检测框、可行驶区域和车道线分割图。本文我将介绍自动驾驶技术及其应用场景,并重点阐述了基于计算机视觉技术下的自动驾驶。自动驾驶技术是一种利用人工智能和…

融柳大铁牛螺蛳粉成功开播,vLive虚拟直播解锁餐饮直播营销新玩法

12月6日&#xff0c;“融柳大铁牛螺蛳粉官方号”成功开播&#xff0c;蓝海创意云为此次直播提供了全程的技术支持。创意云运用自主研发的vLive虚拟直播系统&#xff0c;打造了一场超高品质的沉浸式直播活动&#xff0c;为线上顾客提供了优质的团购体验&#xff0c;同时促进了餐…

VUE3给table的head添加popover筛选、时间去除时分秒、字符串替换某字符

1. VUE3给table的head添加popover筛选 <el-tableref"processTableRef"class"process-table"row-key"secuId":data"pagingData"style"width: 100%"highlight-current-row:height"stockListHeight":default-exp…