二叉树_题目14:114. 二叉树展开为链表

52 阅读2分钟

题目14:114. 二叉树展开为链表

114. 二叉树展开为链表

同类题目

前置知识

题目描述

给你二叉树的根结点 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

进阶: 你可以使用原地算法(O(1) 额外空间)展开这棵树吗?

思路分析

先说结论:后续遍历,使用pre记录上一个遍历的节点,当前节点cur->right = pre; cur->left = nullptr 即可以使用O(1) 的空间复杂度完成。

后续遍历:注意此后续遍历是先遍历右子树

  • 右子树
  • 左子树

程序代码

方法一

 // https://leetcode.cn/problems/flatten-binary-tree-to-linked-list/description/
 //https://leetcode.cn/problems/flatten-binary-tree-to-linked-list/description/
 //114. 二叉树展开为链表
 ​
 #include<iostream>
 #include<vector>
 ​
 using namespace std;
 struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 };
 ​
 class Solution {
 private:
     // 前驱节点
     TreeNode *pre = nullpth;
 public:
     
     void flatten(TreeNode* root) {
         if(root == nullptr)
         {
             return;
         }
         // 右子树
         flatten(root->right);
         // 左子树
         flatten(root->left);
         // 把当前节点的右孩子指向 前驱
         root->right = pre;
         // 左孩子为空
         root->left = nullptr;
         pre = root;
 ​
     }
 };

复杂度分析

时间复杂度O(n),其中 n 是二叉树中的节点个数。每个节点都会遍历一次。

空间复杂度O(1) ,不算递归栈的情况下。

思路分析

把二叉树看成链表,先找前驱节点

1)如果当前节点左子节点不为空,则在其左子树中找到最右边的节点作为前驱节点

  • 前驱节点的右子节点 = 当前节点的右子节点 pre->right = cur->right
  • 当前节点的右子节点 = 当前节点的左子节点 cur->right = cur->left
  • 当前节点的左子节点设为空 cur->left = nullptr

2)如果没有左孩子,那么就直接满足题目要求,处理下一个节点即可

程序代码

方法二

 class Solution {
 public:
     void flatten(TreeNode* root) {
         TreeNode *curr = root;
         while (curr != nullptr) {
             if (curr->left != nullptr) {
                 TreeNode * pre = curr->left;
                 // 找到最右节点,作为前驱
                 while (pre->right != nullptr) {
                     pre = pre->right;
                 }
                 
                 pre->right = curr->right;
                 curr->right = curr->left;
                 curr->left = nullptr;
                 
             }
             // 如果没有左孩子,那么就直接满足题目要求,处理下一个节点即可
             curr = curr->right;
         }
     }
 };

复杂度分析

时间复杂度O(n),其中 n 是二叉树中的节点个数。查找前驱过程中,每个节点最多多访问一次。

空间复杂度O(1)

题目感悟

更多相关知识:github.com/pingguo1987…