题目:
给你二叉树的根结点 root ,请你将它展开为一个单链表:
展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。
示例:
输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]
思路:
方法1,迭代和递归
因为将二叉树展开为单链表的序列顺序就是对二叉树进行先序遍历的顺序,所以可以先对二叉树进行先序遍历,然后再遍历先序遍历序列,改变二叉树的连接结构,从而转换为单链表,这里的单链表也是一个二叉树的结构。
进行先序遍历可以分别使用
迭代
和递归
。这两种方法都占用了额外的空间。
方法2,找前驱节点
这种方法不会占用额外的空间,直接在遍历过程中将二叉树转换为单链表,我们从根节点开始,将根节点的右子树放到左子树的某个位置上,应该放在左子树中最右的位置,按照根左右的遍历顺序,最右的节点就是右子树的前驱节点,放完以后再将整个左子树移动到根节点的右子树位置上,原左子树置为空,下一次遍历到根节点的右分支节点,进行同样的操作,这样一步一步展开为单链表。
注意两种方法在遍历二叉树的过程中都要保留原根节点,使得最后能找到这个原二叉树。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def flatten(self, root):
"""
:type root: TreeNode
:rtype: None Do not return anything, modify root in-place instead.
"""
# plist = []
# # 用递归实现先序遍历
# def preorder(root):
# if root:
# plist.append(root)
# preorder(root.left)
# preorder(root.right)
# preorder(root)
# l = len(plist)
# for i in range(1,l):
# prev = plist[i -1]
# cur = plist[i]
# prev.left = None
# prev.right = cur
# 用迭代实现先序遍历
# plist = []
# stack = []
# node = root # 要保留原根节点,后边要用的
# while node or stack:
# while node:
# plist.append(node)
# stack.append(node)
# node = node.left
# node = stack.pop()
# node = node.right
# l = len(plist)
# for i in range(1,l):
# prev = plist[i -1]
# cur = plist[i]
# prev.left = None
# prev.right = cur
# 以上两种方法都要占用额外空间,这里通过找前驱节点,不占用额外空间
cur = root # 同样保留上当前节点
while cur:
if cur.left:
next = cur.left # 维护这个,一会儿往右边接
pre = cur.left # 开始往右找,找到最右边的节点就是前驱节点
while pre.right:
pre = pre.right # 这样就指向了最右边的节点,而不是空
pre.right = cur.right #把右边的接到了左边的最右边
cur.left = None
cur.right = next
cur = cur.right # 往右边遍历执行同样的操作,直到最后一个节点