当前位置: 首页 > news >正文

LeetCode 热题 100_二叉树展开为链表(46_114_中等_C++)(二叉树;先序遍历(递归+数组);先序遍历(递归))

LeetCode 热题 100_二叉树展开为链表(46_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

题解:

解题思路:

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

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

代码实现

代码实现(思路一(先序遍历(递归+数组))):
//方法一(递归):采用递归的前序遍历将遍历的结点存储在数组中,然后修改指针的指向
void flatten1(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];}
}//先序遍历将结点信息存储在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);
}
代码实现(思路二(先序遍历(非递归))):
//方法二:非递归先序遍历,pre代表当前遍历结点的前一个结点,改变pre左右孩子结点的指向
void flatten2(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 Solution
{
public://方法一(递归):采用递归的前序遍历将遍历的结点存储在数组中,然后修改指针的指向void flatten1(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为nullptrTreeNode* root=createTree(nums);//测试二叉树是否创建正确//inorder_Traversal(root);//二叉树展开为链表Solution s;s.flatten2(root);//输出转换的单链表while (root!=nullptr){cout<<root->val<<"->";root=root->right;}cout<<"nullptr";return 0;
}

LeetCode 热题 100_二叉树展开为链表(46_114)原题链接
欢迎大家和我沟通交流(✿◠‿◠)

http://www.lryc.cn/news/517590.html

相关文章:

  • uniapp实现在card卡片组件内为图片添加长按保存、识别二维码等功能
  • 最好用的图文识别OCR -- PaddleOCR(2) 提高推理效率(PPOCR模型转ONNX模型进行推理)
  • Redis--20--大Key问题解析
  • 新版2024AndroidStudio项目目录结构拆分
  • STM32内置Flash
  • 华为路由器、交换机、AC、新版本开局远程登录那些坑(Telnet、SSH/HTTP避坑指南)
  • 【Linux】深入理解进程信号机制:信号的产生、捕获与阻塞
  • 前端基础技术全解析:从HTML前端基础标签语言开始,逐步深入CSS样式修饰、JavaScript脚本控制、Ajax异步通信以及WebSocket持久通信
  • Linux存储管理之核心秘密(The Core Secret of Linux Storage Management)
  • excel精简使用工具
  • Flutter鸿蒙化 在鸿蒙应用中添加Flutter页面
  • 为什么页面无法正确显示?都有哪些HTML和CSS相关问题?
  • 如何制作一份出色的公司介绍PPT?
  • Selenium 进行网页自动化操作的一个示例,绕过一些网站的自动化检测。python编程
  • HashMap和HashTable的区别
  • 使用redis来进行调优有哪些方案?
  • macOS 中,默认的 Clang 编译器和 Homebrew 安装的 GCC 都不包含 bits/stdc++.h 文件
  • 2012mfc,自绘列表控件
  • vue3运行时执行过程步骤
  • 常用的AT命令,用于查看不同类型的网络信息
  • Vue3组件通讯——自定义事件(子->父)
  • GLSL 着色器语言
  • 如何创建一个 Vue.js 工程
  • Mysql 性能优化:覆盖索引
  • vulnhub靶场【DC系列】之7
  • iOS - 消息机制
  • Wireshark 学习笔记1
  • Oracle OCP考试常见问题之线上考试流程
  • 微信小程序之历史上的今天
  • 记一次k8s下容器启动失败,容器无日志问题排查