题目信息

  • 时间: 2019-06-29

  • 题目链接:Leetcode

  • tag: 二叉搜索树 中序遍历 递归 深度优先搜索

  • 难易程度:中等

  • 题目描述:

    输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

示例:

              4
/ \
2 5
/ \
1 3

我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。

提示

特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。

解题思路

本题难点

二叉搜索树 转换成一个 “排序的循环双向链表” ,其中包含三个要素:

  • 排序链表: 节点应从小到大排序,因此应使用 中序遍历 “从小到大”访问树的节点;

  • 双向链表: 在构建相邻节点(设前驱节点 pre ,当前节点 cur )关系时,不仅应 pre.right=cur ,也应 cur.left=pre 。

  • 循环链表: 设链表头节点 head 和尾节点 tail ,则应构建 head.left=tail 和 tail.right=head 。

具体思路

二叉搜索树的中序遍历为 递增序列

  • 中序遍历

    void dfs(TreeNode root) {
    if(root == null) return;
    dfs(root.left); // 左
    System.out.println(root.val); // 根
    dfs(root.right); // 右
    }

根据以上分析,考虑使用中序遍历访问树的各节点 cur ;并在访问每个节点时构建 cur 和前驱节点 pre 的引用指向;中序遍历完成后,最后构建头节点和尾节点的引用指向即可。

代码

/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right; public Node() {} public Node(int _val) {
val = _val;
} public Node(int _val,Node _left,Node _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
//pre本来是前序节点,随着中序遍历,最终会成为中序遍历的尾节点
//head指向中序遍历的头节点
Node pre,head;
public Node treeToDoublyList(Node root) {
if(root == null){
return null;
}
//深度优先搜索二叉搜索树
dfs(root);
//将头节点head的左指针指向尾节点pre
head.left = pre;
//将尾节点pre的左指针指向头节点head
pre.right = head;
//返回结果
return head; } void dfs(Node cur){
//终止条件: 当节点 cur 为空,代表越过叶节点,直接返回;
if(cur == null){
return;
}
//递归遍历左子树
dfs(cur.left);
//当前节点cur不存在左子树时,此时cur无前驱节点,即前驱节点pre==null,cur为中序遍历的第一个节点
if(pre == null){
//将中序遍历的头节点cur赋予双向链表的头节点head
head = cur;
}else{
//当前节点cur存在前置节点pre,将pre的右指针指向cur
pre.right = cur;
//当前节点cur存在前驱节点pre,将cur的左指针指向pre,形成双向链表
cur.left = pre;
}
//将前驱节点pre后移,保存当前节点cur
pre = cur;
//递归遍历右子树
dfs(cur.right);
}
}

复杂度分析:

  • 时间复杂度 O(N) : N 为二叉树的节点数,中序遍历需要访问所有节点。
  • 空间复杂度 O(N) : 最差情况下,即树退化为链表时,递归深度达到 N,系统使用 O(N) 栈空间。

其他优秀解答

解题思路

中序遍历的非递归,使用栈的先进后出特性。

代码

public Node treeToDoublyList(Node root) {
if(root == null){
return null;
}
//用栈实现
Stack<Node> stack = new Stack<>();
Node current = root;
Node pre = null, head = null;
while(!stack.isEmpty() || current != null) {
//内层循环将当前数据入栈
while(current != null) {
stack.push(current);
current = current.left;
}
//出栈并将该元素放入到链表中
current = stack.pop();
if(pre == null) {//处理头结点
head = current;
}else {
pre.right = current;
current.left = pre;
}
pre = current;
////将cur指向栈顶元素的右孩子
current = current.right;
}
pre.right = head;
head.left = pre;
return head;
}

每日一题 - 剑指 Offer 36. 二叉搜索树与双向链表的更多相关文章

  1. 剑指 Offer 36. 二叉搜索树与双向链表 + 中序遍历 + 二叉排序树

    剑指 Offer 36. 二叉搜索树与双向链表 Offer_36 题目描述 题解分析 本题考查的是二叉树的中序遍历以及二叉排序树的特征(二叉排序树的中序遍历序列是升序序列) 利用排序二叉树中序遍历的性 ...

  2. 剑指 Offer 36. 二叉搜索树与双向链表

    剑指 Offer 36. 二叉搜索树与双向链表 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表.要求不能创建任何新的节点,只能调整树中节点指针的指向. 为了让您更好地理解问题,以下面的 ...

  3. 每日一题 - 剑指 Offer 33. 二叉搜索树的后序遍历序列

    题目信息 时间: 2019-06-26 题目链接:Leetcode tag:分治算法 递归 难易程度:中等 题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果.如果是则返回 tr ...

  4. 每日一题 - 剑指 Offer 54. 二叉搜索树的第k大节点

    题目信息 时间: 2019-07-04 题目链接:Leetcode tag:二叉搜索树 中序遍历 递归 难易程度:中等 题目描述: 给定一棵二叉搜索树,请找出其中第k大的节点. 示例1: 输入: ro ...

  5. 【Java】 剑指offer(36) 二叉搜索树与双向链表

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不 ...

  6. 【剑指Offer】二叉搜索树与双向链表 解题报告(Python)

    [剑指Offer]二叉搜索树与双向链表 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interview ...

  7. 【剑指offer】二叉搜索树转双向链表,C++实现

    原创博文,转载请注明出处! # 题目 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 二叉树节点的定义 struct TreeNod ...

  8. Go语言实现:【剑指offer】二叉搜索树与双向链表

    该题目来源于牛客网<剑指offer>专题. 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. Go语言实现: type T ...

  9. 《剑指offer》二叉搜索树和双向链表

    本题来自<剑指offer> 反转链表 题目: 思路: C++ Code: Python Code: 总结:

随机推荐

  1. Java实现 串中取3个不重复字母

    从标准输入读入一个由字母构成的串(不大于30个字符). 从该串中取出3个不重复的字符,求所有的取法. 取出的字符,要求按字母升序排列成一个串. 不同的取法输出顺序可以不考虑. 例如: 输入: abc ...

  2. Java实现除去次方数

    ** 除去次方数** 自然数的平方数是:1 4 9 16 25 - 自然数的立方数是:1 8 27 64 125 - 自然数的4次方数是:1 16 81 256 - - 这些数字都可以称为次方数. 1 ...

  3. Java实现第八届蓝桥杯纸牌三角形

    纸牌三角形 题目描述 A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算).要求每个边的和相等. 下图就是一种排法(如有对齐问题,参看p1.png). A 9 6 4 8 3 ...

  4. vi命令总结

    VI常用技巧 ​ VI命令可以说是Unix/Linux世界里最常用的编辑文件的命令了,但是因为它的命令集众多,很多人都不习惯使用它,其实您只需要掌握基本命令,然后加以灵活运用,就会发现它的优势,并会逐 ...

  5. java解决poi导出excel文字水印,导出excel不可操作问题

    首先需求是用户提出导出excel数据需使用水印备注其用途: 其实就是在导出excel的同时带有自定义文字水印的导出. 那么我们首先想到的肯定是以一个什么样的思路去解决该问题,首先查找poi导出exce ...

  6. Linux网卡驱动移植--Dm9000网卡驱动分析

    1. Linux网络体系结构由以下5部分组成 ① 系统调用接口: 位于Linux网络子系统的顶部,为应用程序提供访问内核网络子系统的方法,主要指socket系统调用. ② 协议无关接口: 实现一组基于 ...

  7. springMVC 异常

    springMVC  异常 0.依赖(不只是本次案例所需) <?xml version="1.0" encoding="UTF-8"?> <p ...

  8. [蓝桥杯]算法提高 GPA

    问题描述 输入A,B两人的学分获取情况,输出两人GPA之差. 输入格式 输入的第一行包含一个整数n表示A的课程数,以下n行每行Si,Ci分别表示第i个课程的学分与A的表现. GPA=Σ(Si*Ci) ...

  9. Dedecms 修改当前位置样式

    当前列表页间隔符样式修改 后台-->系统基本参数-->核心设置-->栏目位置的间隔符号 只有二级位置栏目时的间隔符去除 找到include文件中的typelink.class.php ...

  10. statsmodels中方差分析表结果解析

    引言 通常我们在对多个变量进行统计分析的时候,结果的汇总和整理需要耗费大量的时间和精力,稍有不慎还有可能出现错误.因此在对多个变量统计分析的时候,使用自动化的脚本对结果进行整理和汇总就十分的方便了. ...