给你二叉树的根结点 root ,请你将它展开为一个单链表:
- 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
- 展开后的单链表应该与二叉树 先序遍历 顺序相同。
分析过程
假设有一颗树
1/ \2 3/ \ / \4 5 6 7
左子树和右子树需要先变化为
1/ \2 5\ \3 6\ \4 7
最后根节点进行变化
1\2\3\4\5\6\7
根节点做了什么?
/*** 实现节点的拉平*/private void nodeNeedTodo(TreeNode node) {// 保存初始左子树TreeNode initLeft = node.left;// 保存初始右子树TreeNode initRight = node.right;// 移除左子树node.left = null;// 将原左子树变成右子树node.right = initLeft;// 遍历获取节点新右子树最末端的右子节点TreeNode temp = node;while (temp.right != null) {temp = temp.right;}// 将初始右子树变成新右子树的右子树temp.right = initRight;}
先操作左子树,然后操作右子树,最后操作根节点 ,和后序遍历二叉树是很类似的
完整算法
public void flatten(TreeNode node) {if (node == null) {return;}// 先让左子树拉平flatten(node.left);// 后让右子树拉平flatten(node.right);// 最后操作根节点拉平nodeNeedTodo(node);}/*** 实现节点的拉平*/private void nodeNeedTodo(TreeNode node) {// 保存初始左子树TreeNode initLeft = node.left;// 保存初始右子树TreeNode initRight = node.right;// 移除左子树node.left = null;// 将原左子树变成右子树node.right = initLeft;// 遍历获取节点新右子树最末端的右子节点TreeNode temp = node;while (temp.right != null) {temp = temp.right;}// 将初始右子树变成新右子树的右子树temp.right = initRight;}
