[Leetcode]28.二叉树展开为链表


题目:给你二叉树的根结点 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]

思想一: 寻找前驱结点,我们发现在前序遍历的时候,在遍历右子树前最后一个遍历的是左子树的最右结点,我们只需要把右子树放到左子树的最右结点的右边,再进行当前结点的左右子树交换,即可实现二叉树的展开。

每次判断结点是否有左节点,如果没有,则已经是排序好的了,再判断他的右节点即可。如果有,那么找他的左孩子的子树的最右结点,找到后把这个结点的右子树指向当前结点的右子树,然后把当前结点的右子树指向左子树,左子树指空。结束条件是向右遍历结束

func flatten(root *TreeNode) {
	cur :=root
	for cur !=nil{
		if cur.Left!=nil{
			next:=cur.Left
			pre := next
			for pre.Right!=nil{
				pre = pre.Right
			}
			pre.Right = cur.Right
			cur.Right = cur.Left
			cur.Left = nil
		}
		cur = cur.Right
	}
}

 思想二:通过上一层的next来解决下层的连接问题。每层的起始结点设置为最左的那个结点。实际上在添加Next结点的时候,会出现两种情况,第一种是父节点的左孩子指向右孩子,这种直接node.Left.Next = node.Right即可,第二种是父节点的右孩子指向父节点的右兄弟的左孩子,这种就需要通过父节点的Next结点的Left来定位,node.Right.Next = node.next.Left,判定条件是父节点是否有Next指向。

func connect(root *Node) *Node {
	if root == nil{
		return root
	}
	for leftmost:=root;leftmost!=nil;leftmost = leftmost.Left{
		for node:=leftmost;node!=nil;node= node.Next{
			node.Left.Next = node.Right
			if node.Next!=nil{
				node.Right.Next = node.next.Left
			}
		}
	}
	return root
}

题目来源:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list