前端算法(69)

54 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

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

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。
输入: root = [1,2,5,3,4,null,6]
输出: [1,null,2,null,3,null,4,null,5,null,6]

题目解析

思路一

我们首先把左子树和右子树都展开为单链表,然后在后序位置把左子树挪到右子树的位置去,右子树再连接到新的最右边的节点下就可以了

/**
 * @param {TreeNode} root
 * @return {void} Do not return anything, modify root in-place instead.
 */
var flatten = function(root) {
    if (root === null) return null;
    // 先把左右子树都展开成单链表
    flatten(root.left);
    flatten(root.right);
    // 后序位置操作
    // 先保存抻平之后的左子树和右子树
    const left = root.left;
    const right = root.right;
    // 左子树挂到节点右侧
    root.left = null;
    root.right = left;
    // 找到新的最右边的节点p
    let p = root;
    while (p.right !== null) {
        p = p.right;
    }
    // 把抻平之后到右子树连上去
    p.right = right;
};

思路二

我们这里使用递归层层向下找到最左的叶子节点,因为该叶子节点没有子节点,也就无需任何处理就可以满足条件,递归回到其父节点,此处需要做的事情是先找出右子节点,再将其作为左子节点,再将左节点作为右子节点,至此结束,然后将已经被拉直的节点树插入到右节点树中,递归会继续进入及其子节点树就可以了

/**
 * @param {TreeNode} root
 * @return {void} Do not return anything, modify root in-place instead.
 */
var flatten = function (root) {
    function flat(node){
        if(!node) return node
        flat(node.left)
        flat(node.right)
        let left = node.left,
         right = node.right
        node.left = null
        node.right = left
        let cur = node
        while(cur.right){
            cur = cur.right
        }
        cur.right = right
    }
    flat(root)
}