【二叉树】Leetcode 114. 二叉树展开为链表【中等】

news2024/11/28 21:38:57

二叉树展开为链表

给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。

示例1:
在这里插入图片描述
输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]

解题思路

展开二叉树为单链表可以使用前序遍历的方式来实现。

  • 1、对于当前节点,首先将其左子树展开为单链表,并将左子树的最右节点连接到当前节点的右子树上。
  • 2、然后将当前节点的右子树展开为单链表。
  • 3、如果左子树不为空,将当前节点的右子树设为展开后的左子树;否则,将左子树设为右子树。

Java实现

public class FlattenBinaryTreeToLinkedList {

    static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int val) {
            this.val = val;
        }
    }

    public void flatten(TreeNode root) {
        if (root == null) {
            return;
        }

        flattenHelper(root);
    }

    private TreeNode flattenHelper(TreeNode node) {
        if (node == null) {
            return null;
        }
        //    1
        //   / \
        //  2   5
        // / \   \
        //3   4   6
        // 把2的右子树4放到2的左子树3的右子树上
        //      1
        //     / \
        //    2   5
        //   / \   \
        //  3   4   6
        //   \
        //    4
        //把2左子树3-4移到右子树下,把2的左子树置空
        //      1
        //     / \
        //    2   5
        //     \   \
        //      3   6
        //       \
        //        4
        //递归,把1的右子树5-6移到1的左子树2-3-4的右子树下
        //      1
        //     / \
        //    2   5
        //     \   \
        //      3   6
        //       \
        //        4
        //         \
        //          5
        //           \
        //            6
        //把1的左子树2-3-4-5-6替换到右子树上,把1的左子树置空
        //      1
        //       \
        //        2
        //         \
        //          3
        //           \
        //            4
        //             \
        //              5
        //               \
        //                6
        //链表符合前序遍历了,并且左子树全为null
        //下面是具体代码实现
        TreeNode leftTail = flattenHelper(node.left);
        TreeNode rightTail = flattenHelper(node.right);


        if (leftTail != null) {
            // 把右子树放到左子树的右子树上
            leftTail.right = node.right;
            // 把(带有右子树的)左子树赋给右子树
            node.right = node.left;
            // 右子树清空
            node.left = null;
        }

//        在这里,rightTail 的优先级最高,然后是 leftTail,最后是 node。
//        这确保了在递归的过程中,当前子树展开后的链表的尾节点是按照
//        右子树、左子树、当前节点的顺序确定的。
//        这样的顺序保证了链表的正确连接,即右子树的尾部接在左子树的尾部,
//        而左子树的尾部接在当前节点的右侧。这样展开后的链表顺序符合二叉树的先序遍历。
        return (rightTail != null) ? rightTail : (leftTail != null) ? leftTail : node;
    }

    // 示例测试
    public static void main(String[] args) {
        FlattenBinaryTreeToLinkedList solution = new FlattenBinaryTreeToLinkedList();

        // 构造示例二叉树
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(5);
        root.left.left = new TreeNode(3);
        root.left.right = new TreeNode(4);
        root.right.right = new TreeNode(6);

        // 调用展开方法
        solution.flatten(root);

        // 打印展开后的链表
        TreeNode current = root;
        while (current != null) {
            System.out.print(current.val + " ");
            current = current.right;
        }
    }
}

时间空间复杂度

  • 时间复杂度:O(n),其中n是二叉树中的节点数,每个节点都需要访问一次。
  • 空间复杂度:O(h),递归调用栈的深度为树的高度。

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

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

相关文章

Linux(CentOS7)配置系统服务以及开机自启动

目录 前言 两种方式 /etc/systemd/system/ 进入 /etc/systemd/system/ 文件夹 创建 nginx.service 文件 重新加载 systemd 配置文件 ​编辑 配置开机自启 /etc/init.d/ 进入 /etc/init.d/ 文件夹 创建 mysql 文件 编写脚本内容 添加/删除系统服务 配置开机自启 …

如何使用Java语言发票查验接口实现发票真伪查验、票据ocr

随着时代潮流的发展,企业也在寻找更加便捷、高效的办公模式,尤其是针对财务工作人员而言,繁琐的发票录入、查验工作占据了财务人员的大部分时间。对此,翔云提供了发票识别接口、发票查验接口,那么企业应当如何将这些接…

笔记本三屏异显方案——更新中,是否能够在FPGA上实现,淘宝购物的价格太贵

三屏是(笔记本电脑屏幕,两个显示器屏幕),异显是采用屏幕的扩展功能,这样能够左边看视频文章,右边control cv代码。 一、 电脑有一个HDMI口的时候,只需要买一个TypeC(雷电接口&#x…

AI大模型在金融行业的应用场景和落地路径

作者:林建明 来源:IT阅读排行榜 本文摘编自《AIGC重塑金融:AI大模型驱动的金融变革与实践》,机械工业出版社出版这是最好的时代,也是最坏的时代。尽管大模型技术在金融领域具有巨大的应用潜力,但其应用也面…

STM32八种I/O口模式

STM32八种I/O口模式 文章目录 STM32八种I/O口模式前言一、stm32八种I/O类型二、区别1.模拟输入2.浮空输入3.上拉输入4.下拉输入5.推挽输出6.开漏输出7.复用推挽输出8.复用推挽输出 总结 前言 作为两年嵌入式软件攻城狮,还没仔细去理解过STM32的GPIO的八种使用模式&…

【蓝桥杯第十三届省赛B】(部分详解)

九进制转十进制 #include <iostream> #include<math.h> using namespace std; int main() {cout << 2*pow(9,3)0*pow(9,2)2*pow(9,1)2*pow(9,0) << endl;return 0; }顺子日期 #include <iostream> using namespace std; int main() {// 请在此…

Vue.js基础指令

(在讲指令之前,可以先了解插值表达式,如果已经知道,当我没说) 一.插值表达式 1.数据绑定最常见的形式就是双大括号的文本插值,Mustache上属性的值替代。只要绑定的数据对象上属性发生了改变,插值处的内容都会更新。,message 是将数据解析成纯文本的,也就是说,就算中…

BM19 寻找峰值(二分查找)

import java.util.*; public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** * param nums int整型一维数组 * return int整型*/public int findPeakElement (int[] nums) {// write code hereint lef…

Thread 之start 和run 的区别

Java Thread 之start 和run 的区别 用start方法来启动线程&#xff0c;真正实现了多线程运行&#xff0c;这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程&#xff0c;这时此线程处于就绪&#xff08;可运行&#x…

持续交付与持续部署相关概念(CD)

目录 一、概述 二、持续交付基本概念 2.1 持续交付的含义 2.1.1 项目管理的视角 2.1.2 产品研发的视角 2.1.3 总结 2.2 持续交付涉及的运作环境 2.2.1 开发环境 2.2.2 测试环境 2.2.3 UAT环境 2.2.4 准生产环境 2.2.5 生产环境 2.3 总结 三、持续部署基本概念 3.…

数据结构八大常见的排序

数据结构八大常见的排序 常见排序算法分类1.插入排序2.希尔排序(缩小增量排序)3.选择排序4.堆排序5.冒泡排序6.快速排序7.归并排序归并排序非递归的实现8.计数排序 常见排序算法分类 1.插入排序 基本思想&#xff1a;把待排序的数组按大小逐个插入到一个已经排好序的有序序列中…

【Java EE】多线程(一)

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更…

物联网实战--入门篇之(六)嵌入式-WIFI驱动(ESP8266)

目录 一、WIFI简介 二、基础网络知识 三、思路讲解 四、代码分析 4.1 状态机制 4.2 客户端连接 4.3 应用数据接收处理 4.4 数据发送 4.5 主函数调用 4.6 网络连接ID分配 五、总结 一、WIFI简介 WIFI在我们生活中太常见了&#xff0c;手机电脑都可以用WiFi连接路由器进行上…

MIT最新研究成果 机器人能够从错误中纠偏 无需编程介入和重复演示

目前科学家们正在努力让机器人变得更加智能&#xff0c;教会他们完成诸如擦拭桌面&#xff0c;端盘子等复杂技能。以往机器人要在非结构化环境执行这样的任务&#xff0c;需要依靠固定编程进行&#xff0c;缺乏场景通用性&#xff0c;而现在机器人的学习过程主要在于模仿&#…

开关恒流源简介

目录 工作原理 设计要点 应用场景 初步想法&#xff0c;为参加活动先占贴&#xff08;带家人出去玩没时间搞~~&#xff09;&#xff0c;后面优化 开关恒流源是一种基于开关电源技术的恒流输出电源设备。它采用开关管进行高速的开关动作&#xff0c;通过控制开关管的导通和截…

linux 一些命令

文章目录 linux 一些命令fdisk 磁盘分区parted 分区文件系统mkfs 格式化文件系统fsck 修复文件系统 mount 挂载swap 交换分区清除linux缓存df du 命令raid 命令基本原理硬raid 和 软raid案例raid 10 故障修复&#xff0c;重启与卸载 lvm逻辑卷技术LVM的使用方式LVM 常见名词解析…

数据库---------完全备份和增量备份的数据恢复,以及断点恢复

目录 一、在数据库表中&#xff0c;分三次录入学生考试成绩 1.1先创建库&#xff0c;创建表&#xff0c;完成三次数据的录入 1.2首次录入成绩后&#xff0c;做该表的完全备份 1.3第二次插入后 做增量备份 1.4第三次插入后 做增量备份 二、模拟数据丢失&#xff0c;并使用…

大文件上传做断点续传(有详细的代码内容)

文章目录 一、是什么分片上传断点续传 二、实现思路三、使用场景小结参考文献 一、是什么 不管怎样简单的需求&#xff0c;在量级达到一定层次时&#xff0c;都会变得异常复杂 文件上传简单&#xff0c;文件变大就复杂 上传大文件时&#xff0c;以下几个变量会影响我们的用户…

标题:Vue3 中父组件向子组件通信的方式

标题&#xff1a;Vue3 中父组件向子组件通信的方式 在 Vue3 中&#xff0c;父组件和子组件之间可以通过一些方式进行通信。其中&#xff0c;父组件向子组件通信主要有两种方式&#xff1a;传值和调用子组件的方法。 一、父组件向子组件传值 当父组件需要向子组件传递数据时&a…

快速排序---算法

1、算法概念 快速排序&#xff1a;通过一趟排序将待排记录分隔成独立的两部分&#xff0c;其中一部分记录的数据均比另一部分的数据小&#xff0c;则可分别对这两部分记录继续进行排序&#xff0c;以达到震哥哥序列有序。 快速排序的最坏运行情况是O()&#xff0c;比如说顺序数…