二叉树--二叉树展开为链表
Posted 算法和数据结构
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树--二叉树展开为链表相关的知识,希望对你有一定的参考价值。
来源:LeetCode
难度:中等
描述:
给你二叉树的根结点 root ,请你将它展开为一个单链表:展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。
例如:
示例1:
示例2:
分析:
该题思路基本和二叉树的前序遍历一致,唯一不同的是咱们需要将遍历过程中的节点保存起来,并且由于需要将链表通过原二叉树root节点的方式进行返回,因此咱们需要将每个二叉树节点通过右子树的方式串连起来,并且将所有节点的左子树置空
解题
方法一:前序遍历法
思路:对原树进行前序遍历,并且利用一个数组将遍历的过程中的节点全部按顺序收集起来。当遍历完成后,将数组中的元素按右节点的方式串连起来,并且将每个节点的左节点置空
代码:
1public void flatten(TreeNode root) {
2 List<TreeNode> list = new ArrayList<TreeNode>();
3 preorderTraversal(root, list);
4 int size = list.size();
5 for (int i = 1; i < size; i++) {
6 TreeNode pre = list.get(i - 1), cur = list.get(i);
7 //左节点置空
8 pre.left = null;
9 //节点之间通过右节点进行串连
10 pre.right = cur;
11 }
12}
13
14//前序遍历
15public void preorderTraversal(TreeNode root, List<TreeNode> list) {
16 if (root != null) {
17 list.add(root);
18 preorderTraversal(root.left, list);
19 preorderTraversal(root.right, list);
20 }
21}
时间复杂度:O(n)
空间复杂度:O(n)
方法一是先进行前序遍历,遍历完之后再进行串连,其实咱们也可以在遍历的过程中就将树的结构进行改变。
方法二:遍历和连接同时进行法
思路:
和非递归前序遍历一样,咱们利用栈存放每个节点。不一样的地方有两点:一是我们要记录上一个出栈的节点,用于和当前节点进行右子树串连;二是我们在入栈的时候需要先将右子树入栈,再将左子树入栈,这样采用达到先遍历左子树,后遍历右子树的效果,这一点和单纯的非递归前序遍历也不一样
代码:
1public void flatten(TreeNode root) {
2 if (root == null) {
3 return;
4 }
5 Stack<TreeNode> stack = new Stack<>();
6 stack.push(root);
7 //记录上一个节点
8 TreeNode prev = null;
9 while (!stack.isEmpty()) {
10 TreeNode curr = stack.pop();
11 if (prev != null) {
12 //将上一个节点和当前节点串连起来
13 prev.left = null;
14 prev.right = curr;
15 }
16 //将当前节点的左右子树入栈,需要注意先入右子树,再入左子树
17 TreeNode left = curr.left, right = curr.right;
18 if (right != null) {
19 stack.push(right);
20 }
21 if (left != null) {
22 stack.push(left);
23 }
24 //将上一个节点替换为当前已出栈的节点
25 prev = curr;
26 }
27}
时间复杂度:O(n)
空间复杂度:O(n)
以上仅是个人思路解法,觉得还不错欢迎点赞关注分享
往期精彩推荐
以上是关于二叉树--二叉树展开为链表的主要内容,如果未能解决你的问题,请参考以下文章