🚩传送门:牛客题目
题目
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:![[NC]52. 二叉搜索树与双向链表 - 图1](/uploads/projects/mylearn@leetcode/1e21349d4edde12908235d8bb6aee181.png)
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。![[NC]52. 二叉搜索树与双向链表 - 图2](/uploads/projects/mylearn@leetcode/dd3547da60570fd6c151a689fa511d01.png)
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
要求:空间复杂度(即在原树上操作),时间复杂度
示例 1:
输入:root = [4,2,5,1,3] 输出:[1,2,3,4,5] 解释:下图显示了转化后的二叉搜索树,实线表示后继关系,虚线表示前驱关系。
解题思路:递归中序遍历
本文解法基于性质:二叉搜索树的中序遍历为 递增序列 。
将 二叉搜索树 转换成一个 “排序的循环双向链表” ,其中包含三个要素:
- 排序: 节点应从小到大排序,因此应使用 中序遍历 “从小到大”访问树的节点。
双向: 在构建相邻节点的引用关系时,设前驱节点
_pre_和当前节点_cur_这样可以利用
_pre.right = cur_,_cur.left = pre_完成双向的构建循环: 设链表头节点
_head_,尾结点_tail_。完成双向构建后,将
head.left = tail,tail.right = head头结点:当遇到第一个结点,即head未初始化时,应当将当前结点置为头结点 尾结点:当 DFS 中序遍历递归结束时,pre指向的就是尾结点
🚩主要就是利用前驱节点 _pre_ 和当前节点 _cur_ ,依靠中序遍历,完成双向设置。
复杂度分析
时间复杂度:,其中
为二叉搜索树结点数 。
空间复杂度:
我的代码
public class Solution {TreeNode Head;TreeNode pre;public void DFS(TreeNode cur){// 空指针返回if(cur==null) return;// 指针非空递归左子树DFS(cur.left);// 当前结点非空,若Head没初始化说明是初始态,当前结点应置为头结点if(Head==null) Head=cur;else{// 此时说明当前是中间态cur.left=pre;pre.right=cur;}pre=cur;DFS(cur.right);}public TreeNode Convert(TreeNode pRootOfTree) {DFS(pRootOfTree);// 如果不是循环双向链表就取消这一语句块{Head.left=pre;pre.right=Head;}return Head;}}
