二叉树展开为链表-力扣114

296 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述

现有一个二叉树根节点 root,请你将他展开为一个单链表:

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

image.png
输入:

root = [1,2,5,3,4,null,6]

输出:

[1,null,2,null,3,null,4,null,5,null,6]

二叉树节点结构如下:

type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

二、思路分析

本题要求将一颗二叉树按前序遍历的顺序转换为一个单链表,并要求二叉树中节点的左右指针在转换为单链表时分别指向 null 和链表下一个节点。首先我们可以通过二叉树前序遍历,将节点按顺序存入到切片中,之后再遍历切片,更改左右指针,重组单链表。

在前序遍历二叉树时可以使用递归和非递归两种方式

// 递归遍历
func preorder (root *TreeNode) {
    if root == nil{
            return 
    }
    // do something
    preorder(root.Left)
    preorder(root.Right)
}
// 非递归遍历
func preorder (root *TreeNode) {
    if root == nil{
            return
    }
    stack := []*TreeNode{}
    for root != nil || len(stack) != 0{
        if root != nil{
            // do something
            stack = append(stack, root)
            root = root.Left
        }else{
            root = stack[len(stack)-1]
            stack = stack[:len(stack)-1]
            root = root.Right
	}
    }
}

三、代码

func flatten(root *TreeNode)  {
    list := preorder(root)
    for i:=1; i<len(list); i++{
        pre, cur := list[i-1], list[i]
        pre.Left, pre.Right = nil, cur
    }
}

func preorder (root *TreeNode) []*TreeNode {
    list := make([]*TreeNode, 0)	
    if root == nil{
        return list
    }
    list = append(list, root)
    list = append(list, preorder(root.Left)...)
    list = append(list, preorder(root.Right)...)
    return list
}

四、总结

本题使用了前序遍历+链表重组的方式将二叉树转换为单链表,时间复杂度以及空间复杂度均为 O(n)。本题还可以通过寻找前驱结点的方式来解决,找到当前节点前序遍历的最后一个节点,作为前驱节点,将当前节点的右子树赋给前驱节点,之后将当前节点的左子树连接到右子树上,并将左子树赋值为 null。按如上步骤依次遍历所有节点。