每日一题 - 剑指 Offer 36. 二叉搜索树与双向链表
题目信息
时间: 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. 二叉搜索树与双向链表的更多相关文章
- 剑指 Offer 36. 二叉搜索树与双向链表 + 中序遍历 + 二叉排序树
剑指 Offer 36. 二叉搜索树与双向链表 Offer_36 题目描述 题解分析 本题考查的是二叉树的中序遍历以及二叉排序树的特征(二叉排序树的中序遍历序列是升序序列) 利用排序二叉树中序遍历的性 ...
- 剑指 Offer 36. 二叉搜索树与双向链表
剑指 Offer 36. 二叉搜索树与双向链表 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表.要求不能创建任何新的节点,只能调整树中节点指针的指向. 为了让您更好地理解问题,以下面的 ...
- 每日一题 - 剑指 Offer 33. 二叉搜索树的后序遍历序列
题目信息 时间: 2019-06-26 题目链接:Leetcode tag:分治算法 递归 难易程度:中等 题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果.如果是则返回 tr ...
- 每日一题 - 剑指 Offer 54. 二叉搜索树的第k大节点
题目信息 时间: 2019-07-04 题目链接:Leetcode tag:二叉搜索树 中序遍历 递归 难易程度:中等 题目描述: 给定一棵二叉搜索树,请找出其中第k大的节点. 示例1: 输入: ro ...
- 【Java】 剑指offer(36) 二叉搜索树与双向链表
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不 ...
- 【剑指Offer】二叉搜索树与双向链表 解题报告(Python)
[剑指Offer]二叉搜索树与双向链表 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interview ...
- 【剑指offer】二叉搜索树转双向链表,C++实现
原创博文,转载请注明出处! # 题目 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 二叉树节点的定义 struct TreeNod ...
- Go语言实现:【剑指offer】二叉搜索树与双向链表
该题目来源于牛客网<剑指offer>专题. 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. Go语言实现: type T ...
- 《剑指offer》二叉搜索树和双向链表
本题来自<剑指offer> 反转链表 题目: 思路: C++ Code: Python Code: 总结:
随机推荐
- java实现第八届蓝桥杯数位和
数位和 题目描述 数学家高斯很小的时候就天分过人.一次老师指定的算数题目是:1+2+-+100. 高斯立即做出答案:5050! 这次你的任务是类似的.但并非是把一个个的数字加起来,而是对该数字的每一个 ...
- 「MoreThanJava」机器指令到汇编再到高级编程语言
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- ThinkPHP6.0 + Vue + ElementUI + axios 的环境安装到实现 CURD 操作!
官方文档地址: ThinkPHP6.0: https://www.kancloud.cn/manual/thinkphp6_0/1037479 ElemetUI: https://elemen ...
- [每日一题2020.06.12]P3375 【模板】KMP字符串匹配
题目链接 关于kmp : https://www.cnblogs.com/roccoshi/p/13096988.html 关于kmp, 想了很久, 我觉得不应该放在这里写, 另开一贴记录一下. #i ...
- 03.DRF-设计方法
RESTful设计方法 1. 域名 应该尽量将API部署在专用域名之下. https://api.example.com 如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下. https:/ ...
- ca75a_c++_标准IO库-利用流对象把文件内容读取到向量-操作文件
/*ca75a_c++_标准IO库习题练习习题8.3,8.4,8.6习题8.9.8.10 ifstream inFile(fileName.c_str());1>d:\users\txwtech ...
- 利用VS自带发布功能实现web项目快速部署
你还在使用最原始的方法部署服务器吗?还在把项目文件全部复制然后黏贴到服务器上?这种方法太low而且又慢又不安全(存在源码泄露等安全性问题),如果你是这样,那你自己肯定也为此烦恼不已. 下面我所要讲到的 ...
- 基于SSM框架的新生报到可视化系统
1.本课题的目的及意义 新生报到数据一直是困扰着各大高校的管理性问题,人数多.工作量大,这无疑是一个挑战,也因此加快了高校的信息化建设步伐.随着互联网的普及与发展,日常生活中人们接触到的数据正以惊人的 ...
- 事务的特性ACID、隔离级别
1.事务特性ACID 1.1 事务的四大特性 1.原子性(Atomicity) 事务包装的一组sql,要么都执行成功,要么都失败.这些操作是不可分割的. 2.一致性(Consistency) 数据库的 ...
- WeChair项目Alpha冲刺(4/10)
团队项目进行情况 1.昨日进展 Alpha冲刺第四天 昨日进展: 前端完成小程序登录态的定义 LoginController编写初步完成同时修改并更新了代码,但是在将编码好的项目部署到服务器上时 ...