完整教程:LeetCode 面试经典 150_二叉树_二叉树展开为链表(74_114_C++_中等)

题目描述:

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

题解:

解题思路:

思路一(先序遍历(递归+数组)):

1、在进行先序遍历的时候先将结点的信息存储到数组中,通过数组中的先后顺序更新每个结点的指向。

2、复杂度分析:
① 时间复杂度:O(n),n为二叉树中节点的个数,需遍历一遍二叉树O(n),遍历一遍数组更改指针的指向O(n)。
② 空间复杂度:O(n),递归遍历所需空间最多为O(n),一个额外的数组存储二叉树的信息O(n)。

思路二(先序遍历(非递归)):

1、如果我们采用非递归的方式,当我们遍历到一个结点时,我们就可以用一个指针来记录先序遍历中上一个结点的信息,通过修改上一个结点的指向来转换成单链表。

3、复杂度分析
① 时间复杂度:O(n),n为二叉树中节点的个数,需遍历一遍二叉树O(n)。
② 空间复杂度:O(n),先序遍历的非递归实现需要借助栈实现,最坏情况下栈中有n个结点信息。

代码实现

代码实现(思路一(先序遍历(递归+数组))):
//方法一(递归):采用递归的前序遍历将遍历的结点存储在数组中,然后修改指针的指向
class Solution1 {
private:
//先序遍历将结点信息存储在nums_TreeNode中
//注意vector<TreeNode *>&nums_TreeNode这里的引用(&)
  void preorder(TreeNode *root,vector<TreeNode *>&nums_TreeNode){
    if(root==nullptr) return;
    nums_TreeNode.emplace_back(root);
    preorder(root->left,nums_TreeNode);
    preorder(root->right,nums_TreeNode);
    }
    public:
    void flatten(TreeNode* root) {
    //nums_TreeNode存放先序遍历各节点的顺序
    vector<TreeNode *>nums_TreeNode;
      //先序遍历将结点信息存储在nums_TreeNode中
      preorder(root,nums_TreeNode);
      //根据nums_TreeNode中结点的顺序更改结点的指向
      for (int i = 1; i < nums_TreeNode.size(); i++)
      {
      nums_TreeNode[i-1]->left=nullptr;
      nums_TreeNode[i-1]->right=nums_TreeNode[i];
      }
      }
      };
代码实现(思路二(先序遍历(非递归))):
//方法二:非递归先序遍历,pre代表当前遍历结点的前一个结点,改变pre左右孩子结点的指向
class Solution2 {
public:
void flatten(TreeNode* root) {
if(root==nullptr) return ;
stack<TreeNode *>stk;
  stk.push(root);
  //存放展开单链表的末尾
  TreeNode *tail=nullptr;
  while (!stk.empty())
  {
  TreeNode *node=stk.top();
  stk.pop();
  //更改结点的指向
  if(tail!=nullptr) {
  tail->left=nullptr;
  tail->right=node;
  }
  //注意右子结点先入栈
  if(node->right!=nullptr) stk.push(node->right);
  if(node->left!=nullptr) stk.push(node->left);
  //更新单链表的尾结点
  tail=node;
  }
  }
  };
以思路一为例进行调试
#include<iostream>
  #include<vector>
    #include<queue>
      #include<stack>
        using namespace std;
        struct TreeNode
        {
        int val;
        TreeNode *left;
        TreeNode *right;
        TreeNode():val(0),left(nullptr),right(nullptr){}
        TreeNode(int val):val(val),left(nullptr),right(nullptr){}
        TreeNode(int val,TreeNode *left,TreeNode *right):val(val),left(left),right(right){}
        };
        //通过数组创建二叉树,数组中-1代表nullptr
        TreeNode *createTree(vector <int> nums){
          if (nums.empty()) return nullptr;
          TreeNode *root=new TreeNode(nums[0]);
          queue<TreeNode *> q;
            q.push(root);
            int i=1;
            while (i<nums.size())
            {
            //注意这里不能用root,会改变root的指向
            TreeNode *node=q.front();
            q.pop();
            if(i<nums.size()&&nums[i]!=-1){
            node->left=new TreeNode(nums[i]);
            q.push(node->left);
            }
            ++i;
            if(i<nums.size()&&nums[i]!=-1){
            node->right=new TreeNode(nums[i]);
            q.push(node->right);
            }
            ++i;
            }
            return root;
            }
            //中序遍历输出二叉树,用于验证二叉树是否创建正确
            void inorder_Traversal(TreeNode *root){
            if(root==nullptr) return;
            inorder_Traversal(root->left);
            cout<<root->val<<" ";
              inorder_Traversal(root->right);
              }
              class Solution1
              {
              public:
              //方法一(递归):采用递归的前序遍历将遍历的结点存储在数组中,然后修改指针的指向
              void flatten(TreeNode* root) {
              vector<TreeNode *>nums_TreeNode;
                preorder(root,nums_TreeNode);
                for (int i = 1; i < nums_TreeNode.size(); i++)
                {
                nums_TreeNode[i-1]->left=nullptr;
                nums_TreeNode[i-1]->right=nums_TreeNode[i];
                }
                }
                //注意vector<TreeNode *>&nums_TreeNode这里的引用(&)
                  void preorder(TreeNode *root,vector<TreeNode *>&nums_TreeNode){
                    if(root==nullptr) return;
                    nums_TreeNode.emplace_back(root);
                    preorder(root->left,nums_TreeNode);
                    preorder(root->right,nums_TreeNode);
                    }
                    };
                    int main(){
                    vector<int> nums={1,2,5,3,4,-1,6};
                      //通过数组创建二叉树,-1为nullptr
                      TreeNode* root=createTree(nums);
                      //测试二叉树是否创建正确
                      //inorder_Traversal(root);
                      //二叉树展开为链表
                      Solution1 s;
                      s.flatten1(root);
                      //输出转换的单链表
                      while (root!=nullptr)
                      {
                      cout<<root->val<<"->";
                        root=root->right;
                        }
                        cout<<"nullptr";
                        return 0;
                        }

LeetCode 面试经典 150_二叉树_二叉树展开为链表(74_114)原题链接
欢迎大家和我沟通交流(✿◠‿◠)

posted @ 2026-02-11 08:15  clnchanpin  阅读(13)  评论(0)    收藏  举报