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

文章目录

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

题目

标题和出处

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

出处: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)。注意返回值不计入空间复杂度。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【STM32单片机】简易电子琴设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用STM32F103C8T6单片机控制器&#xff0c;使用数码管模块、矩阵按键、无源蜂鸣器等。 主要功能&#xff1a; 系统运行后&#xff0c;蜂鸣器播放一首音乐&#xff0c;进入电子琴模式&#xff0c;…

“大病来前,脚先知”!若是你的脚部有6个表现,或是大病信号

脚是人的“根”&#xff0c;一棵大树是否繁盛取决于根。当根部枯萎时&#xff0c;树木就会率先枯竭&#xff0c;而脚就是人体老化的征兆。因此&#xff0c;有一句古老的谚语&#xff0c;“大病来临之前脚先知”&#xff0c;这意味着可以通过观察脚的运动表现来预测大病的迹象。…

从零开发短视频电商 JMH压测真实示例DEMO

文章目录 原理依赖基础示例结果main 关键注解示例BenchmarkWarmupMeasurementBenchmarkModeOutputTimeUnitForkThreadsStateSetup 和 TearDownParam 问题DeadCode常量折叠Loops JMH 测试的对象可以是任一方法&#xff0c;颗粒度更小&#xff0c;例如本地方法&#xff0c;Rest A…

【数据结构】手撕排序

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、排序的概念及其运用1.1 排序的概念1.2 常见的算法排序 二、 冒泡排序三、直接插入排…

微信公众号的服务器验证方法

服务器上的操作&#xff1a; 将下面的wx.py文件放在服务器上&#xff0c;运行python3 wx.py 80 # -*- coding: utf-8 -*- # filename: main.py import web import handle import hashlibclass WeChatHandler(object):def GET(self):data web.input()if len(data) 0:return &…

回溯算法:递增子序列 全排列 全排列II

491.递增子序列 思路&#xff1a; 分析题目&#xff1a; 输入一个序列&#xff0c;输出至少有两个元素的递增子序列。所谓序列&#xff0c;就是按照次序排好的行列&#xff0c;因此本题不可以把输入数组重新排序&#xff0c;否则就会改变序列的顺序。因此&#xff0c;不能使用…

C# WPF上位机开发(抽奖软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 每到年末或者是尾牙的时候&#xff0c;很多公司都会办一些年终的清楚活动&#xff0c;感谢员工过去一年辛苦的付出。这个时候&#xff0c;作为年会…

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

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

Dockerfile 指令的最佳实践

这些建议旨在帮助您创建一个高效且可维护的Dockerfile。 一、FROM 尽可能使用当前的官方镜像作为镜像的基础。Docker推荐Alpine镜像&#xff0c;因为它受到严格控制&#xff0c;体积小&#xff08;目前不到6 MB&#xff09;&#xff0c;同时仍然是一个完整的Linux发行版。 FR…

【技术分享】利用双网口透传网关实现三菱FX3U PLC远程程序上下载监控

准备工作 一台可联网操作的电脑一台双网口的远程透传网关及博达远程透传配置工具网线两条&#xff0c;用于实现网络连接及连接PLC一台三菱 FX3U PLC及其编程软件一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&#xff09; …

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

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

安装Centos7

作者&#xff1a;余小小 下载VMware15 参考&#xff1a;http://t.csdnimg.cn/saS9S 下载镜像 这里使用网易镜像库下载 网易开源镜像站http://mirrors.163.com/ 网易Centos下载http://mirrors.163.com/centos/7.7.1908/isos/x86_64/ 安装Centos系统&#xff08;基础设施&…

云安全技术包括哪些?

云安全技术是随着云计算技术的发展而衍生出来的一种安全技术&#xff0c;它利用云计算的分布式处理和数据存储能力&#xff0c;实现对海量数据的快速处理和存储&#xff0c;同时采用机器学习和人工智能技术对数据进行分析和挖掘&#xff0c;以便更好地发现和防御安全威胁。云安…

Java常见算法和lambda

查找算法 public class day11 {public static void main(String[] args) {//基本查找 / 顺序差宅//核心://从0索引开始挨个往后查找//需求:定义一个方法利用基本查找 查询某个元素是否存在//数据如下:{131,127,147,81,103,23,7,79}int[] arr{131,127,147,81,103,23,7,79};int…

如何高效管理多个微信?

看倒这个标题&#xff0c;你是否有以下烦恼&#xff1a; 1.微信账号太多&#xff0c;管理过于麻烦 2.微信号多&#xff0c;需要很多员工来管理&#xff0c;人工费用多 3.多个微信打开后会造成微信登陆界面过多&#xff0c;切换操作十分不方便 4.当微信多的时候&#xff0c;…

mfc140u.dll文件下载的方法指南,教你多种方法修复mfc140u.dll

在面对诸如"mfc140u.dll文件丢失"或者"mfc140u.dll错误"等问题时&#xff0c;许多用户可能会考虑直接从互联网上下载该DLL文件来快速解决问题。确实&#xff0c;此类错误信息经常在尝试运行某些软件&#xff0c;特别是依赖于 Microsoft Visual C Redistrib…

运行时更改Android应用程序图标

设想一下&#xff0c;当我们正在开发一款应用。随着某个节日的临近&#xff0c;我们可能希望通过更改应用图标来增强用户的节日氛围&#xff0c;例如在图标上添“新年特惠”或者“龙年大吉”等标签。 这种小小的改变看似不经意&#xff0c;却能够吸引用户的注意。 运行时更改应…

【Unity动画】Unity 2D动画创建流程

本文以2D为案例&#xff0c;讲解Unity 播放动画的流程 准备和导入2D动画资源 外部导入序列帧生成的 Unity内部制作的 外部导入的3D动画 2.创建动画过程 打开时间轴Ctrl6 选中场景中的一个未来需要播放动画的物体 回到时间轴点击Create一个新动画片段 拖动2D动画资源放入…

记录:Unity脚本的编写10.0

目录 前言实验1: 仿真系统的UI主界面设计1.实验目的2.实验内容3.实验步骤 实验2&#xff1a;仿真系统功能实现1.实验目的2.实验内容3.实验步骤 前言 之前内容的集大成者&#xff0c;一个游戏小demo&#xff0c;虽然很简陋但是还是有一些东西的 实验1: 仿真系统的UI主界面设计…

鸿蒙开发ServiceAbility基本概念

时间过长&#xff0c;开发者必须在Service里创建新的线程来处理&#xff08;详见线程间通信&#xff09;&#xff0c;防止造成主线程阻塞&#xff0c;应用程序无响应。 创建Service 介绍如何创建一个Service 创建Service的代码示例如下&#xff1a;查看获取鸿蒙开发 (qq.com)…