LeetCode 👉 HOT 100 👉 二叉树展开为链表 - 中等题

197 阅读2分钟

「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」。

题目

给你二叉树的根结点 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]

思路

从题意可知,单链表的顺序,是二叉树按照 前序遍历 的得到的结果;那么先用 前序遍历,将每个节点放入一个数组 stack 中,这样就会得到如下的结果

[节点1, 节点2, 节点3, ....,  最后的节点]

然后会发现,如果遍历这个数组,将节点1的左节点指向 null,将节点1的右节点指向节点二,重复这个步骤,直到遍历完成,原有的二叉树,就会变成符合题意的链表。

不熟悉二叉树前、中、后序遍历的,可以先看这篇 二叉树的中、先、后序遍历

完整代码如下

    /**
     * Definition for a binary tree node.
     * function TreeNode(val, left, right) {
     *     this.val = (val===undefined ? 0 : val)
     *     this.left = (left===undefined ? null : left)
     *     this.right = (right===undefined ? null : right)
     * }
     */
    /**
     * @param {TreeNode} root
     * @return {void} Do not return anything, modify root in-place instead.
     */
    var flatten = function(root) {
        const stack = [];

        // 前序遍历
        const traver = node => {
            if(!node) return;
            stack.push(node);
            traver(node.left);
            traver(node.right);
        }
        traver(root);

        // 遍历每个节点
        for(let i = 1; i < stack.length; i++) {
            const prev = stack[i - 1], cur = stack[i];

            prev.right = cur;
            prev.left = null;
        }
        
    };

思考: 做些优化,在遍历二叉树的过程中,可以这么做,如果当前节点存在右节点,将右节点放入 stack 中,将左节点放在右节点上,继续遍历这个左节点,重复上述过程,每次遍历时更新当前节点为 lasrNode 最后一个节点,定义上述过程为一个函数 dfs(root);这样遍历完成后,会得到:

二叉树的左节点都放在右节点上了

一个保存了所有右节点的 stack

一个 lastNode 指向二叉树的最后一个节点

这时候从 stack 取出最后一个节点 node,放在 lastNode 的右节点上,同时对 node 使用上述函数 dfs,当 stack 不为空时,重复上述算法;

优化后代码

    
    /**
     * @param {TreeNode} root
     * @return {void} Do not return anything, modify root in-place instead.
     */
    var flatten = function(root) {
        const stack = [];

        let lastNode = root

        const dfs = node => {
            if(!node) return;
            lastNode = node;
            if(node.right) stack.push(node.right);

            node.right = node.left;

            dfs(node.left)
            
            node.left = null;
        }

        dfs(root);

        // stack 不为空时 取出最后一个节点
        while(stack.length) {
            let currentNode = stack.pop();

            lastNode.right = currentNode;

            dfs(lastNode.right);

            lastNode.left = null;
        }

小结

二叉树的遍历,熟能生巧~

LeetCode 👉 HOT 100 👉 二叉树展开为链表 - 中等题

合集:LeetCode 👉 HOT 100,有空就会更新,大家多多支持,点个赞👍

如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄