码迷,mamicode.com
首页 > 其他好文 > 详细

二叉树展开成链表

时间:2020-05-30 22:05:09      阅读:83      评论:0      收藏:0      [点我收藏+]

标签:binary   empty   复杂度   while   后序遍历   时间   bsp   不为   先来   

 

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

 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)

二叉树展开成链表

标签:binary   empty   复杂度   while   后序遍历   时间   bsp   不为   先来   

原文地址:https://www.cnblogs.com/hi3254014978/p/12989749.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!