数据结构与算法之深入解析“二叉树展开为链表”的求解思路与算法示例
Posted Serendipity·y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法之深入解析“二叉树展开为链表”的求解思路与算法示例相关的知识,希望对你有一定的参考价值。
一、题目要求
- 给你二叉树的根结点 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。
二、求解算法
① 先序遍历
- 将左子树插入到右子树的地方;
- 将原来的右子树接到左子树的最右边节点;
- 考虑新的右子树的根节点,一直重复上边的过程,直到新的右子树为 null。
- 将 1 的左子树插入到右子树的地方:
- 将原来的右子树接到左子树的最右边节点:
- 将 2 的左子树插入到右子树的地方:
- 将原来的右子树接到左子树的最右边节点:
- Java 示例:
public void flatten(TreeNode root)
while (root != null)
// 左子树为 null,直接考虑下一个节点
if (root.left == null)
root = root.right;
else
// 找左子树最右边的节点
TreeNode pre = root.left;
while (pre.right != null)
pre = pre.right;
// 将原来的右子树接到左子树的最右边节点
pre.right = root.right;
// 将左子树插入到右子树的地方
root.right = root.left;
root.left = null;
// 考虑下一个节点
root = root.right;
② 递归
- 题目其实就是将二叉树通过右指针,组成一个链表:
1 -> 2 -> 3 -> 4 -> 5 -> 6
- 我们知道给定的遍历顺序其实就是先序遍历的顺序,所以能不能利用先序遍历的代码,每遍历一个节点,就将上一个节点的右指针更新为当前节点。
- 先序遍历的顺序是 1 2 3 4 5 6;
- 遍历到 2,把 1 的右指针指向 2:1 -> 2 3 4 5 6;
-
- 遍历到 3,把 2 的右指针指向 3:1 -> 2 -> 3 4 5 6。
- … …
- 一直进行下去似乎就解决了这个问题。但现实是残酷的,原因就是把 1 的右指针指向 2,那么 1 的原本的右孩子就丢失了,也就是 5 就找不到了。
- 解决方法的话,可以逆过来进行:
-
- 依次遍历 6 5 4 3 2 1,然后每遍历一个节点就将当前节点的右指针更新为上一个节点;
-
- 遍历到 5,把 5 的右指针指向 6:6 <- 5 4 3 2 1;
-
- 遍历到 4,把 4 的右指针指向 5:6 <- 5 <- 4 3 2 1。
- … …
- 这样就不会有丢失孩子的问题了,因为更新当前的右指针的时候,当前节点的右孩子已经访问过了。而 6 5 4 3 2 1 的遍历顺序其实变形的后序遍历,遍历顺序是右子树->左子树->根节点。
- Java 示例:
public void flatten(TreeNode root)
Stack<TreeNode> toVisit = new Stack<>();
TreeNode cur = root;
TreeNode pre = null;
while (cur != null || !toVisit.isEmpty())
while (cur != null)
toVisit.push(cur); // 添加根节点
cur = cur.right; // 递归添加右节点
cur = toVisit.peek(); // 已经访问到最右的节点了
// 在不存在左节点或者右节点已经访问过的情况下,访问根节点
if (cur.left == null || cur.left == pre)
toVisit.pop();
/**************修改的地方***************/
cur.right = pre;
cur.left = null;
/*************************************/
pre = cur;
cur = null;
else
cur = cur.left; // 左节点还没有访问过就先访问左节点
以上是关于数据结构与算法之深入解析“二叉树展开为链表”的求解思路与算法示例的主要内容,如果未能解决你的问题,请参考以下文章
⭐算法入门⭐《二叉树》中等01 —— LeetCode 114. 二叉树展开为链表
LeetCode114 二叉树展开为链表 ---二叉树题 三种解法 (递归) (迭代) (前驱节点)