首页 > 其他分享 >图解LeetCode——剑指 Offer 36. 二叉搜索树与双向链表

图解LeetCode——剑指 Offer 36. 二叉搜索树与双向链表

时间:2023-05-23 11:05:40浏览次数:33  
标签:node Node head cur Offer 36 链表 节点

一、题目

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

二、示例

为了让您更好地理解问题,以下面的二叉搜索树为例:

图解LeetCode——剑指 Offer 36. 二叉搜索树与双向链表_二叉搜索树

我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。

图解LeetCode——剑指 Offer 36. 二叉搜索树与双向链表_链表_02

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

三、解题思路

根据题目描述,我们要将一颗二叉搜索树转换成为一个排序的循环双向链表。这里有两个重要的信息:

信息1】这是一颗二叉搜索树,那么这个二叉树就具有Node.left.val < Node.val < Node.right.val的特点。
信息2】要构建一个排序的 循环的 双向链表

那么针对“信息1”,我们可以采用中序遍历的方式对二叉搜索树种的各个节点执行遍历操作。那么对于中序遍历,我们采用的代码结构如下所示:

void dfs(Node node) {
    ... ...
    dfs(node.left); // 处理左子节点
	node // 处理当前节点
    dfs(node.right); // 处理右子节点
	... ...
}

那么针对“信息2”,我们需要一个循环的双向链表,那么这个循环就需要我们创建两个指针了,即:头指针Node head和尾指针Node cur(在程序执行过程中,cur表示正在处理的那个节点,所以当整个二叉搜索树都遍历完毕后,cur就是双向链表中最末尾的那个节点了)。那么,当整个搜索二叉树都遍历完毕之后,我们就可以通过执行:head.left = curcur.right = head来将双向链表的收尾相连。

上面就是整个题目的解题思路了,下面我们还是按照惯例,以输入:[4,2,5,1,3]为例,看一下具体拼装有序双向循环链表的过程是怎么样子的。请见下图所示:

图解LeetCode——剑指 Offer 36. 二叉搜索树与双向链表_链表_03

四、代码实现

class Solution {
    Node head, cur;
    public Node treeToDoublyList(Node root) {
        if (root == null) return root;
        dfs(root);
        head.left = cur;
        cur.right = head;
        return head;
    }
    void dfs(Node node) {
        if (node == null) return;
        dfs(node.left);
        if (head == null) {
            head = cur = node;
        } else {
            cur.right = node;
            node.left = cur;
            cur = node;
        }
        dfs(node.right);
    }
}

图解LeetCode——剑指 Offer 36. 二叉搜索树与双向链表_双向链表_04

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

标签:node,Node,head,cur,Offer,36,链表,节点
From: https://blog.51cto.com/u_15003301/6330108

相关文章

  • FZU 2236(离散化+树状数组)
    【离散化】借此题记一下离散化。离散化:当题目数据很大时,但数的个数不多,可以采用离散化,降低数值,便于计算。例如数列{89,14,9,1000,2};离散化后:{4,3,2,5,1};(此操作后,数值整体降低,甚至可以当数组下标使用了)具体操作参见本题代码。离散化三部曲:1.数组ha[]存储所有存在过的......
  • 图解LeetCode——剑指 Offer 07. 重建二叉树
    一、题目输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。二、示例2.1>示例1:【输入】preorder=[3,9,20,15,7],inorder=[9,3,15,20,7]【输出】[3,9,20,null,null,15,7]2.2>示例2:【输入】pr......
  • 图解LeetCode——剑指 Offer 29. 顺时针打印矩阵
    一、题目输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。二、示例2.1>示例1:【输入】matrix=[[1,2,3],[4,5,6],[7,8,9]]【输出】[1,2,3,6,9,8,7,4,5]2.2>示例2:【输入】matrix= [[1,2,3,4],[5,6,7,8],[9,10,11,12]]【输出】[1,2,3,4,8,12,11,10,9,5,6,7]限......
  • 图解LeetCode——剑指 Offer 15. 二进制中1的个数
    一、题目编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为'1'的个数(也被称为 汉明重量)。二、示例2.1>示例1:【输入】n=11(控制台输入00000000000000000000000000001011)【输出】3【解释】输入的二进制串000000000000000000000000000010......
  • 复杂链表的复制
       ......
  • c++打卡练习(36)
    求多项式的和以50为例S=1+1/2+1/2*3+1/2*3*4+......1/2*3*.....*50流程图:伪代码:源代码:#include<iostream>usingnamespacestd;intmain(){ doublea=1,b,num,N; cout<<"输入你想阶乘到的最大数"<<endl; cin>>N; for(inti=1;i<=N;i++){ a*=i; b=1/a; num......
  • 软件评价:360浏览器
    软件作品:360浏览器相关评价1.用户界面360浏览器的用户界面采用了简洁、清晰的设计风格,主要特色是绿色和蓝色主题的颜色搭配。它的界面布局相对传统,类似于大多数主流浏览器,但同时增加了一些自己的特色功能,比如"沙盘沉浸式浏览"和"网址卡片"等。对于部分用户而言,360浏览器的界面......
  • 剑指 Offer 58 - II. 左旋转字符串
    剑指Offer58-II.左旋转字符串</br></br>题目:字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。示例1:输入:s="abcdefg",k......
  • 剑指 Offer 05. 替换空格
    剑指Offer05.替换空格</br></br>题目:请实现一个函数,把字符串s中的每个空格替换成"%20"。示例:输入:s="Wearehappy."输出:"We%20are%20happy."限制:0<=s的长度<=10000</br></br>思路1:可以通过实例化出一个新的string对象,通过对原来字符串进行遍历,将原字符......
  • 5-21打卡:双循环链表(无哨兵)练习
    #include<iostream>usingnamespacestd;typedefstructNode{intdata;Node*next;Node*pre;}Node;Node*initlist(intdata){Node*node=newNode;node->data=data;node->next=node;node->pre=node;......