二叉树展开成链表

Posted hi3254014978

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树展开成链表相关的知识,希望对你有一定的参考价值。

 

先来一个前序遍历把所有结点存在一个列表中,然后遍历链表,把所有结点用右指针串起来

 1 /**
 2  * Definition for a binary tree node.
 3  * public class TreeNode {
 4  *     int val;
 5  *     TreeNode left;
 6  *     TreeNode right;
 7  *     TreeNode() {}
 8  *     TreeNode(int val) { this.val = val; }
 9  *     TreeNode(int val, TreeNode left, TreeNode right) {
10  *         this.val = val;
11  *         this.left = left;
12  *         this.right = right;
13  *     }
14  * }
15  */
16 class Solution {
17     public void flatten(TreeNode root) {
18         if(root == null)
19             return ;
20         List<TreeNode> list = new ArrayList<>();
21         TreeNode top = root;
22         Stack<TreeNode> stack = new Stack<>();
23         // 先来一个前序遍历把所有结点存在一个列表中
24         while(!stack.empty() || top != null){
25             while(top != null){
26                 list.add(top);
27                 stack.push(top);
28                 top = top.left;
29             }
30             top = stack.pop();
31             top = top.right;
32         }
33 
34         // 遍历链表,把所有结点用右指针串起来
35         int n = list.size();
36         for(int i = 0; i < n; i++){
37             if(i > 0){
38                 list.get(i - 1).right = list.get(i);
39             }
40             list.get(i).left = null;
41         }
42     }
43 }

力扣测试:时间为2ms, 空间为39MB

复杂度分析:

时间复杂度:一次存,一次遍历,相当于遍历了两次二叉树,所以时间复杂度为O(n), n为节点个数

空间复杂度:列表的大小,所以为O(n)

 思路二:

1. 把当前结点的右子树挂到左子树最右边的结点上

2. 把左子树挂到右子树上、

3. 更新当前结点的右子树为新的当前结点,重复上面的操作,直到当前结点为空

 1 class Solution {
 2     public void flatten(TreeNode root) {
 3         TreeNode cur = root;
 4         while(cur != null){
 5             // 如果左子树为空,直接进入下个结点
 6             if(cur.left == null){
 7                 cur = cur.right;
 8             }else{
 9                 // 如果左子树不为空,找到它最右边的结点
10                 TreeNode leftRight = cur.left;
11                 while(leftRight.right != null){
12                     leftRight = leftRight.right;
13                 }
14                 // 将右子树挂到这个结点上
15                 leftRight.right = cur.right;
16 
17                 // 将左子树挂到右子树的位置
18                 cur.right = cur.left;
19                 cur.left = null;
20 
21                 // 更新cur指针
22                 cur = cur.right;
23             }
24         }
25        
26     }
27 }

力扣测试时间为:1ms, 空间为39.2mb

复杂度分析:

这个时间复杂度不太好判断,我觉得应该是O(nlogn),首先总体对每个结点必须访问一次,所以是O(n), 其次内层循环中每次都必须找到左子树最右边的结点,我觉得这个复杂度应该是O(logn),所以我觉的时间复杂度是O(nlogn)

空间复杂度为O(1)

思路三:巧用后序遍历

1. 右、左、根的后序遍历,遍历结果为6->5->4->3->2->1

2. 使用p->right = pre, 即可把逆序编程正序,变为把 1->2->3->4->5->6,pre结点刚好是p结点的左结点,所以不用担心左结点会丢失,

 1 class Solution {
 2     public void flatten(TreeNode root) {
 3         // 右、左、根的后序遍历,遍历结果为6->5->4->3->2->1
 4         // 使用p->right = pre, 即可把逆序编程正序,变为把 1->2->3->4->5->6,pre结点刚好是p结点的左结点,所以不用担心左结点会丢失,
 5         postTraversal(root);
 6     }
 7     public TreeNode pre = null;
 8     public void postTraversal(TreeNode p){
 9         if(p != null){
10             postTraversal(p.right);
11             postTraversal(p.left);
12             p.right = pre;
13             p.left = null;
14             pre = p;
15         }
16     }
17 }

力扣测试时间为0ms, 空间为39.8MB

复杂度分析:

时间复杂度为:仅仅是一次后序遍历,所以复杂度为O(n)

空间复杂度:方法栈最大递归层数为树的高度,所以空间复杂度为O(n)

以上是关于二叉树展开成链表的主要内容,如果未能解决你的问题,请参考以下文章

[LintCode] Flatten Binary Tree to Linked List 将二叉树展开成链表

LeetCode 114| Flatten Binary Tree to Linked List(二叉树转化成链表)

leetcode 114二叉树转换成链表

LeetCode(114): 二叉树展开为链表

453 将二叉树拆成链表

二叉树红黑树以及Golang实现红黑树