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

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个结点信息。

代码实现

代码实现(思路一(先序遍历(递归+数组))):
cpp 复制代码
//方法一(递归):采用递归的前序遍历将遍历的结点存储在数组中,然后修改指针的指向
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];
	    }
    }
};
代码实现(思路二(先序遍历(非递归))):
cpp 复制代码
//方法二:非递归先序遍历,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;
	    }
    }
};
以思路一为例进行调试
cpp 复制代码
#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)原题链接

欢迎大家和我沟通交流(✿◠‿◠)

相关推荐
做怪小疯子2 小时前
LeetCode 热题 100——双指针——三数之和
算法·leetcode·职场和发展
sin_hielo3 小时前
leetcode 2536
数据结构·算法·leetcode
flashlight_hi3 小时前
LeetCode 分类刷题:203. 移除链表元素
算法·leetcode·链表
py有趣3 小时前
LeetCode算法学习之数组中的第K个最大元素
学习·算法·leetcode
吗~喽3 小时前
【LeetCode】将 x 减到 0 的最小操作数
算法·leetcode
cookies_s_s3 小时前
C++20 协程
linux·开发语言·c++
牛客企业服务3 小时前
2025年AI面试防作弊指南:技术笔试如何识别异常行为
人工智能·面试·职场和发展
hetao17338374 小时前
2025-11-13~14 hetao1733837的刷题记录
c++·算法
hansang_IR4 小时前
【题解】洛谷 P2476 [SCOI2008] 着色方案 [记搜]
c++·算法·记忆化搜索