ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

114. 二叉树展开为链表

2021-03-28 19:33:53  阅读:197  来源: 互联网

标签:right 链表 114 二叉树 null root 节点 flatten


114. 二叉树展开为链表

Difficulty: 中等

给你二叉树的根结点 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) 额外空间)展开这棵树吗?

Solution

方法一:摘抄自 labuladong 大佬的解析

链接:https://labuladong.gitbook.io/algo/shu-ju-jie-gou-xi-lie/shou-ba-shou-shua-er-cha-shu-xun-lian-di-gui-si-wei/er-cha-shu-xi-lie-1

给 flatten 函数输入一个节点 root,那么以 root 为根的二叉树就会被拉平为一条链表。
我们再梳理一下,如何按题目要求把一棵树拉平成一条链表?很简单,以下流程:

1、将 root 的左子树和右子树拉平。

2、将 root 的右子树接到左子树下方,然后将整个左子树作为右子树。
在这里插入图片描述

// 定义:将以 root 为根的树拉平为链表
void flatten(TreeNode root) {
    // base case
    if (root == null) return;

    flatten(root.left);
    flatten(root.right);

    /**** 后序遍历位置 ****/
    // 1、左右子树已经被拉平成一条链表
    TreeNode left = root.left;
    TreeNode right = root.right;

    // 2、将左子树作为右子树
    root.left = null;
    root.right = left;

    // 3、将原先的右子树接到当前右子树的末端
    TreeNode p = root;
    while (p.right != null) {
        p = p.right;
    }
    p.right = right;
}

你看,这就是递归的魅力,你说 flatten 函数是怎么把左右子树拉平的?说不清楚,但是只要知道 flatten 的定义如此,相信这个定义,让 root 做它该做的事情,然后 flatten 函数就会按照定义工作。另外注意递归框架是后序遍历,因为我们要先拉平左右子树才能进行后续操作。

方法二:leetcode讨论区感觉很牛逼的大佬分享,而且我竟然也看懂了
在这里插入图片描述
其实是分为三步:

  • 首先将根节点的左子树变成链表
  • 其次将根节点的右子树变成链表
  • 最后将变成链表的右子树放在变成链表的左子树的最右边

这就是一个递归的过程,递归的一个非常重要的点就是:不去管函数的内部细节是如何处理的,我们只看其函数作用以及输入与输出。对于函数flatten来说:

  • 函数作用:将一个二叉树,原地将它展开为链表
  • 输入:树的根节点
  • 输出:无

那我们就直接根据三步来写程序就可以了

class Solution {
    public void flatten(TreeNode root) {
        if(root == null){
            return ;
        }
        //将根节点的左子树变成链表
        flatten(root.left);
        //将根节点的右子树变成链表
        flatten(root.right);
        TreeNode temp = root.right;
        //把树的右边换成左边的链表
        root.right = root.left;
        //记得要将左边置空
        root.left = null;
        //找到树的最右边的节点
        while(root.right != null) root = root.right;
        //把右边的链表接到刚才树的最右边的节点
        root.right = temp;
    }
}

作者:Geralt_U
链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/solution/114-er-cha-shu-zhan-kai-wei-lian-biao-by-ming-zhi-/
来源:力扣(LeetCode)著作权归作者所有.

总结(看了大佬自己的想法):这两种方法感觉很类似,其中最重要的一点是,不管二叉树的左右子树是怎样变成链表(直线),因为都是通过递归在函数flatten内部完成,只知道函数flatten执行完成之后,左右子树就都变成链表了;一开始看的时候,自己就很纠结,总是想深入通过执行函数,一步一步的去看看,内部是怎样完成的,结果,发现自己陷入内部递归,陷进去了。脑子转不出来了;没办法看看了大佬解析,自己瞬间就想通了。

自己一直有个误区:其实对待二叉树遍历的题目,无非就是遍历循环或者递归,那么方法可能就是:

  • 前序遍历: 根 左 右
  • 中序遍历: 左 根 右
  • 后序遍历: 左 右 根
  • 层次遍历

对于上面两种大佬解释,其实可以发现前序遍历的影子,先进行根节点的处理,在处理左右两个节点。

  • 前序遍历
    // 前序遍历
    if(root == null){
            return ;
    }
    flatten(root.left);
    flatten(root.right);
  • 剩下部分代码:可以理解为只是对当前节点的操作,对当前节点的左右子树的操作,因为是递归,对根节点的操作:将根节点的右子树拼接到根节点的左子树;同样的道理,由于递归,左子树同样可以看做是一棵二叉树,那么依然可以做上面类似的操作,将以左子树的根节点为首,这个节点左右子数拼接,这样一层层的递归拼接,最终完成了题目的要求

标签:right,链表,114,二叉树,null,root,节点,flatten
来源: https://blog.csdn.net/shanggushenlong/article/details/115285485

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有