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

算法刷题记录——LeetCode篇(2.2) [第111~120题](持续更新)

更新时间:2025-04-04

  • 算法题解目录汇总:算法刷题记录——题解目录汇总
  • 技术博客总目录:计算机技术系列博客——目录页

优先整理热门100及面试150,不定期持续更新,欢迎关注!


114. 二叉树展开为链表

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

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

示例 1:

输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [0]
输出:[0]

提示:

  • 树中结点数在范围 [0, 2000] 内
  • -100 <= Node.val <= 100

进阶:
你可以使用原地算法(O(1) 额外空间)展开这棵树吗?

方法一:迭代先序遍历(显式栈)

利用栈模拟先序遍历,维护前驱节点prev,实时修改指针建立链表。

  • 核心思想:利用栈按「根→右→左」顺序压入节点,确保弹出顺序为「根→左→右」。
  • 指针调整:维护前驱节点prev,每次将prevright指向当前节点,并清空left指针。
  • 空间优化:栈的深度为树高,平均空间复杂度为O(log n)

代码实现(Java):

public class Solution {
    public void flatten(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        TreeNode prev = null;
      
        while (!stack.isEmpty()) {
            TreeNode current = stack.pop();
            // 将前驱节点的right指向当前节点,left置空
            if (prev != null) {
                prev.right = current;
                prev.left = null;
            }
            prev = current;
            // 先压入右子节点,再压入左子节点(栈的LIFO特性)
            if (current.right != null) stack.push(current.right);
            if (current.left != null) stack.push(current.left);
        }
    }
}

方法二:递归后序遍历(连接左右子树)

递归处理左右子树,将左子树连接到右子树之前,并更新末尾节点。

  • 核心思想:将左子树末尾连接到右子树头部,再让根节点指向左子树。
  • 末尾处理:返回展开后的最后一个节点,避免每次遍历链表末尾,时间复杂度优化至O(n)
  • 逻辑简化:通过后序遍历自底向上处理,确保左子树完全展开后再处理根节点。

代码实现(Java):

public class Solution {
    public void flatten(TreeNode root) {
        flattenHelper(root);
    }
  
    private TreeNode flattenHelper(TreeNode node) {
        if (node == null) return null;
        // 递归处理左右子树,获取展开后的末尾节点
        TreeNode leftTail = flattenHelper(node.left);
        TreeNode rightTail = flattenHelper(node.right);
      
        // 将左子树插入到当前节点与右子树之间
        if (node.left != null) {
            leftTail.right = node.right;
            node.right = node.left;
            node.left = null;
        }
        // 返回当前子树展开后的最后一个节点
        return (rightTail != null) ? rightTail : 
               (leftTail != null) ? leftTail : node;
    }
}

复杂度分析

  • 时间复杂度:两种方法均为 O(n),每个节点被访问一次。
  • 空间复杂度
    • 迭代法:O(h),h为树高,最坏情况(链表结构)为O(n)
    • 递归法:O(h),递归栈深度为树高。

对比总结

  • 迭代法:适合大规模数据或树结构较深时,避免递归栈溢出。
  • 递归法:代码简洁,适合对代码可读性要求高,且无栈溢出风险的场景。

声明

  1. 本文版权归 CSDN 用户 Allen Wurlitzer 所有,遵循CC-BY-SA协议发布,转载请注明出处。
  2. 本文题目来源 力扣-LeetCode ,著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

相关文章:

  • 濮阳自适应网站建设关键词大全
  • java网站建设天津网站排名提升
  • 网站备案备的是域名还是空间爱战网关键词挖掘查询工具
  • 去黄山旅游攻略和费用是多少河北seo基础入门教程
  • wordpress 农家乐seo关键词推广优化
  • php外贸网站制作武汉网站建设方案优化
  • STM32F103C8T6实现 SG90 360 °舵机转动
  • RabbitMQ应用问题
  • Ubuntu挂载HDD迁移存储PostgreSQL数据
  • 哈尔滨工业大学:大模型时代的具身智能
  • [ctfshow web入门] web2
  • Error in v-on handler: “TypeError: handler.apply is not a function“
  • 支持selenium的chrome driver更新到135.0.7049.42
  • 智能测试用例生成:分块实现大模型完整回答的最佳策略
  • Python作业1 if __name__==‘__main__‘
  • Spring Boot整合MyBatis-Plus实现CRUD操作教程
  • 【CMake】《CMake构建实战:项目开发卷》笔记-Chapter10-策略与向后兼容
  • C++信号与槽机制自实现
  • win10 笔记本电脑安装 pytorch+cuda+gpu 大模型开发环境过程记录
  • git push
  • 蓝桥杯单片机频率
  • YOLO环境搭建,win11+wsl2+ubuntu24+cuda12.6+idea
  • C# Winform 入门(9)之如何封装并调用dll
  • 如何提高rabbitmq消费效率
  • C#中为自定义控件设置工具箱图标
  • OpenRouter - 创建 API Keys、OpenAI 调用 以及在Cline 中配置使用