Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述
现有一个二叉树根节点 root,请你将他展开为一个单链表:
- 展开后的单链表应该同样使用 TreeNode,其中 right 子指针指向链表中下一个节点,而左指针始终为 null。
- 展开后的单链表应该与二叉树先序遍历顺序相同。
输入:
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。按如上步骤依次遍历所有节点。