每日一题 - 剑指 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 问题描述 在计算机科学中,预排序是一种很古老的思想.实际上,对于排序算法的兴趣很大程度上是因为这样一个事实:如果列表是有序的,许多关于列表的问题更容易求解.显然,对于包含了排序操作,这种算法的时间 ...
- 【asp.net core 系列】4. 更高更强的路由
0. 前言 在之前我们介绍了请求通过路由寻找到控制器,以及控制器与视图的数据流转.那么,我们回过头来,再看看路由的一些其他用法. 1. 路由属性(Route Attribute) 按照英文的直接翻译, ...
- unittest单元测试框架入门及应用
一.简介 unittest是Python单元测试框架.unittest它支持自动化测试,在测试中使用setup(初始化)和shutdown(关闭销毁)操作,组织测试 用例为套件(批量运行),以及把测试 ...
- php开发环境和框架phalcon的搭建
0x01 在ubuntu 12.04 上安装lnmp环境. 安装nginx (Centos install nginx repo wget http://www.atomicorp.com/ins ...
- Cypress系列(0)- 如何学习 Cypress
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 前言 Cypress 未来很有可能会火的 ...
- 「MoreThanJava」Java发展史及起航新世界
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- LeetCode 76,一题教会你面试算法时的思考套路
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题的第45篇文章,我们一起来看看LeetCode的76题,最小窗口子串Minimum Window Substrin ...
- 利用struts2进行单个文件,批量文件上传,ajax异步上传以及下载
利用struts2进行单个文件,批量文件上传,ajax异步上传以及下载 1.页面显示代码 <%@ page language="java" import="java ...
- 使用CURL和火车头软件采集搜狐文章
直接上代码: //参数1:访问的URL,参数2:post数据(不填则为GET),参数3:提交的$cookies,参数4:是否返回$cookies function curl_request($url, ...
- 科学计算:Python 分析数据找问题,并图形化
对于记录的数据,如何用 Python 进行分析.或图形化呢? 本文将介绍 numpy, matplotlib, pandas, scipy 几个包,进行数据分析.与图形化. 准备环境 Python 环 ...