二叉搜索树与双向链表的解题记录

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

题目

  • 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
  • 将循环双向链表中最小元素作为根节点,并返回。

二叉搜索树定义

  • 或者是一棵空树,或者是具有下列性质的二叉树: (来源:二叉搜索树百度百科)
    • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    • 它的左、右子树也分别为二叉排序树。
  • 特点:其中序遍历的结果是一个有序序列,即按左、中、右的顺序遍历该树,得到升序序列;按右、中、左的顺序遍历,将得到降序序列(见剑指 Offer 54. 二叉搜索树的第k大节点)。
    在这里插入图片描述

题解

  1. 通过对该二叉搜索树的中序遍历可以得到排序序列。

    // 中序遍历
    const inorderTravel = (root) => {
        if (!root) { return }
        // 左
        inorderTravel(root.left)
    	// 中
        handleCurNode(root)
    	// 右
        inorderTravel(root.right)
      }
    
  2. 对于某节点curNode和其前驱节点preNode,分别按以下规则修改指针指向,即可得到双向链表;修改头、尾节点的指针指向,得到循环链表。

    • preNode.right = curNode
    • curNode.left = preNode
// 前驱节点为null,该节点是中序遍历序列中最小的节点,作为头节点
if (!preNode) {
  head = root
}

if (preNode) {
  preNode.right = root
}
root.left = preNode
// 更新前驱节点,进入下一个节点的处理
preNode = root

在这里插入图片描述

var treeToDoublyList = function(root) {
  let preNode = null
  let head = null
  
  const inorderTravel = (root) => {
    if (!root) { return }
    
    inorderTravel(root.left)
    if (!preNode) {
      head = root
    }
    if (preNode) {
      preNode.right = root
    }
    root.left = preNode
    preNode = root

    inorderTravel(root.right)
  }

  inorderTravel(root)
  
  // head和最后一个仍然没有双向绑定
  head.left = preNode
  preNode.right = head
  
  return head

};
  1. 复杂度分析
  • 时间复杂度:与树的高度有关
    • 完全二叉树是最优效率,时间复杂度为O(lgn)
    • 退化为链表,即只有左子树或只有右子树时,时间复杂度为O(n)
  • 空间复杂度:同理,若为完全二叉树,递归O为(lgn),开辟O(lgn)栈空间;退化为链表,递归深度为O(n),开辟O(n)栈空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值