leetcode日记(96)有序链表转换二叉搜索树

devtools/2025/3/15 1:40:14/

这么多天以来学到最多的一道题。

这题真的是把链表和树的知识综合起来了,需要融会贯通。

有两种做法,很遗憾自己写的时候一种都没想出来,只想到将链表先转换为数组这种简单方法……

第一个知识点是快慢指针,这种做法在找出长链表的二分点、三分点很常用,只需要遍历一遍就能得到链表的二分位置。

具体做法是设置快慢指针,快指针一次走两步,慢指针一次走一步,在快指针到达链表末尾时慢指针正好到达链表的二分位置。

通过这种方法,我们每次遍历找出链表中点,将中点作为前链表终点和后链表起点,再将前链表和后链表遍历分别作为中点树的左右子树,如此反复递归,即可得到最终树。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
/*** Definition for a binary tree node.* 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 {
public:ListNode* head;TreeNode* structual(ListNode* left,ListNode* right){if(left==right||left==NULL) return nullptr;ListNode* quick=left;ListNode* slow=left;while(quick!=right&&quick->next!=right){quick=quick->next;quick=quick->next;slow=slow->next;}TreeNode* tree=new TreeNode(slow->val);tree->left=structual(left,slow);tree->right=structual(slow->next,right);return tree;}TreeNode* sortedListToBST(ListNode* head) {this->head=head;return structual(head,nullptr);}
};

需要注意的一点是循环快慢指针时while的判断条件应有两个,因为链表长度有奇偶两种情况。

还有这里的left,right区间是左闭右开,意思是左被包含在左链表,右不包含在右链表(因为一开始的right是nullptr,而且在tree->left递归时right也就是slow不必后退,单向链表也不方便后退)。

第二种方法我觉得特别巧妙,没有利用快慢指针,而是利用中序遍历。

因为链表的顺序就是最后生成树的中序遍历,所以除了最初遍历链表得到链表长度,之后就不必遍历链表,而是每次取链表长度的中间数切分,这时不需要立刻添加中间节点的val,而是预留着,先遍历中间数前面的数,在等左子树全部有了数之后再去添加中间数的val。

这种做法不需要遍历多次链表,而是用序号代替链表位置,只要传入链表头节点,每次递归使节点变为next,然后就可以直接按照链表顺序添入树。

可以说是非常巧妙了。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
/*** Definition for a binary tree node.* 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 {
public:TreeNode* dg(ListNode*& list,int begin,int end){if(begin>end||list==NULL) return nullptr;int middle=(begin+end)/2;TreeNode* tree=new TreeNode();tree->left=dg(list,begin,middle-1);tree->val=list->val;list=list->next;tree->right=dg(list,middle+1,end);return tree;}TreeNode* sortedListToBST(ListNode* head) {ListNode* h=head;int length=0;while(h!=NULL){h=h->next;length++;}return dg(head,0,length-1);}
};

需要注意的是这里的left和right是左闭右闭,也就是right也要包含进树里,因为传入的左右节点其实是序号,只需要序号-1就可以传入左子树了,所以要顺便注意开始传入的是length-1。

另外还有一个特别要注意的地方,递归函数传入的ListNode*应该要加&,因为节点是要不断变化的,需要传入指针,才能在为中间节点赋值前让list后移。


http://www.ppmy.cn/devtools/167166.html

相关文章

Android的tablayout+ViewPager2,缓存的数量有容量上限吗?

Android的tablayoutViewPager2,ViewPager2里面有6个fragment,不断切换不同的tab,那么ViewPager2会缓存6个fragment吗,还是缓存的数量有容量上限? DeepSeek R1 思考 61 秒 思考过程 好的,我现在要回答用户…

java学习总结(四):MyBatis

一、MyBatis介绍 像MyBatis、Hibernate都是属于ORM框架 对象关系映射(英语:(Object Relational Mapping,简称ORM) MySql、Oracle、SqlServer都是关系型数据库 1、O->R add/insert/save studentDao.insert(student) 把一个java对象保…

React hook钩子性能优化Hooks的面试常考题目

根据,提到了常用的Hooks有useState、useEffect、useContext、useReducer、useCallback、useMemo、useRef,还有其他如useLayoutEffect和useImperativeHandle。和也提到了类似的Hooks,并且强调了useEffect的重要性。详细解释了useState、useEffect、useMemo和useCallback的区别…

PHP与数据库连接常见问题及解决办法

PHP与数据库连接常见问题及解决办法 在现代Web开发中,PHP与数据库的连接是不可或缺的一部分。无论是构建动态网站、内容管理系统(CMS)还是电子商务平台,PHP与数据库的交互都是核心功能之一。然而,在实际开发过程中&am…

第27周JavaSpringboot 前后端联调

电商前后端联调课程笔记 一、项目启动与环境搭建 1.1 项目启动 在学习电商项目的前后端联调之前,需要先掌握如何启动项目。项目启动是整个开发流程的基础,只有成功启动项目,才能进行后续的开发与调试工作。 1.1.1 环境安装 环境安装是项…

SpringBoot3+Lombok如何配置logback输出日志到文件

Background/Requirement SpringBoot3Lombok如何配置logback输出日志到文件,因为我需要对这些日志进行输出,控制台输出和文件输出,文件输出是为了更好的作为AuditLog且支持滚动式备份,每天一个文件。 Technical Solution 1.确保你…

Python 入门教程(2)搭建环境 2.4、VSCode配置Node.js运行环境

文章目录 一、VSCode配置Node.js运行环境 1、软件安装2、安装Node.js插件3、配置VSCode4、创建并运行Node.js文件5、调试Node.js代码 一、VSCode配置Node.js运行环境 1、软件安装 安装下面的软件: 安装Node.js:Node.js官网 下载Node.js安装包。建议选…

如何利用Python爬虫获取微店商品详情数据:实战指南

微店作为知名的电商平台,提供了丰富的商品资源。通过Python爬虫技术,可以高效地获取微店商品的详情数据,用于数据分析、研究或其他用途。本文将详细介绍如何使用Python编写爬虫程序,获取微店商品的详情数据,并确保爬虫…