LeetCode-114. 二叉树展开为链表【栈 树 深度优先搜索 链表 二叉树】

LeetCode-114. 二叉树展开为链表【栈 树 深度优先搜索 链表 二叉树】

题目描述:

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

解题思路一:前序遍历,迭代,递归

将二叉树展开为单链表之后,单链表中的节点顺序即为二叉树的前序遍历访问各节点的顺序。因此,可以对二叉树进行前序遍历,获得各节点被访问到的顺序。由于将二叉树展开为链表之后会破坏二叉树的结构,因此在前序遍历结束之后更新每个节点的左右子节点的信息,将二叉树展开为单链表。

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def flatten(self, root: Optional[TreeNode]) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        if not root:
            return
        stack = []
        preorder = []
        cur = root
        while stack or cur:
            if cur:
                stack.append(cur)
                preorder.append(cur.val)
                cur = cur.left
            else:
                cur = stack.pop()
                cur = cur.right
        h = root
        for i in range(1, len(preorder)):
            h.right = TreeNode(preorder[i])
            h.left = None
            h = h.right
# 或者
class Solution:
    def flatten(self, root: TreeNode) -> None:
        preorderList = list()
        stack = list()
        node = root

        while node or stack:
            while node:
                preorderList.append(node)
                stack.append(node)
                node = node.left
            node = stack.pop()
            node = node.right
        
        size = len(preorderList)
        for i in range(1, size):
            prev, curr = preorderList[i - 1], preorderList[i]
            prev.left = None
            prev.right = curr
# 递归
class Solution:
    def flatten(self, root: TreeNode) -> None:
        preorderList = list()

        def preorderTraversal(root: TreeNode):
            if root:
                preorderList.append(root)
                preorderTraversal(root.left)
                preorderTraversal(root.right)
        
        preorderTraversal(root)
        size = len(preorderList)
        for i in range(1, size):
            prev, curr = preorderList[i - 1], preorderList[i]
            prev.left = None
            prev.right = curr

时间复杂度:O(n)

空间复杂度:O(n)

解题思路二:寻找前驱节点

前两种方法都借助前序遍历,前序遍历过程中需要使用栈存储节点。有没有空间复杂度是 O(1)O(1)O(1) 的做法呢?

注意到前序遍历访问各节点的顺序是根节点、左子树、右子树。如果一个节点的左子节点为空,则该节点不需要进行展开操作。如果一个节点的左子节点不为空,则该节点的左子树中的最后一个节点被访问之后,该节点的右子节点被访问。该节点的左子树中最后一个被访问的节点是左子树中的最右边的节点,也是该节点的前驱节点。因此,问题转化成寻找当前节点的前驱节点。

具体做法是,对于当前节点,如果其左子节点不为空,则在其左子树中找到最右边的节点,作为前驱节点,将当前节点的右子节点赋给前驱节点的右子节点,然后将当前节点的左子节点赋给当前节点的右子节点,并将当前节点的左子节点设为空。对当前节点处理结束后,继续处理链表中的下一个节点,直到所有节点都处理结束。

https://leetcode.cn/problems/flatten-binary-tree-to-linked-list/solutions/356853/er-cha-shu-zhan-kai-wei-lian-biao-by-leetcode-solu

python 复制代码
class Solution:
    def flatten(self, root: TreeNode) -> None:
        curr = root
        while curr:
            if curr.left:
                predecessor = nxt = curr.left
                while predecessor.right:
                    predecessor = predecessor.right
                predecessor.right = curr.right
                curr.left = None
                curr.right = nxt
            curr = curr.right

时间复杂度:O(n)

空间复杂度:O(1)

解题思路三:0

python 复制代码

时间复杂度:O(n)

空间复杂度:O(n)

相关推荐
海石5 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石5 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
gugucoding7 小时前
31. 【C语言】堆栈与队列的实现
c语言·开发语言·数据结构·链表
ChaoZiLL8 小时前
我的数据结构3——链表(link list)
数据结构·链表
网络与设备以及操作系统学习使用者17 小时前
通信的物理与逻辑双维度解析
学习·深度优先
tachibana218 小时前
hot100 排序链表(148)
java·数据结构·算法·leetcode·链表
不能跑的代码不是好代码19 小时前
二叉树从基础概念到LeetCode实战
算法·leetcode
凯瑟琳.奥古斯特19 小时前
二分查找解力扣1011最优运载能力
开发语言·c++·算法·leetcode·职场和发展
Yang_jie_0320 小时前
笔记:数据结构(链表)
数据结构·笔记·链表
YuK.W1 天前
Leetcode100: 70.爬楼梯、118.杨辉三角、198.打家劫舍
java·算法·leetcode