前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一天一大 lee(有序链表转换二叉搜索树)难度:中等-Day20200818

一天一大 lee(有序链表转换二叉搜索树)难度:中等-Day20200818

作者头像
前端小书童
发布2020-09-24 14:24:27
4230
发布2020-09-24 14:24:27
举报
文章被收录于专栏:前端小书童
题目:[1]

给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例

代码语言:javascript
复制
给定的有序链表: [-10, -3, 0, 5, 9],

一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:

      0
     / \
   -3   9
   /   /
 -10

抛砖引玉

本题为链表转换成平衡二叉树,之前做过将有序数组转换平衡二叉树:

20200703:将有序数组转换为二叉搜索树 (难度:简单)[2]

可以发现数组转换成平衡二叉树的主要逻辑为找到数组中点。

再回到本题,能想到最简单的方法就是讲链表转换成数组,然后就可以借用之前数组的逻辑完成了

抛砖引玉

代码语言:javascript
复制
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {ListNode} head
 * @return {TreeNode}
 */
var sortedListToBST = function (head) {
  let nums = []
  while (head) {
    nums.push(head.val)
    head = head.next
  }
  return build(nums, 0, nums.length - 1)
  function build(nums, left, right) {
    if (left > right) return null
    let mid = parseInt((left + right) / 2, 10)
    let node = new TreeNode(nums[mid])
    node.left = build(nums, left, mid - 1)
    node.right = build(nums, mid + 1, right)
    return node
  }
}

分治

相较于数组,链表没有索引,通过一个元素的 next 指向下一个元素 但是同样,我们也可以变量链表找到链表的中心位置

那么问题就转换成了求链表的中心位置:

官方题解:快慢指针法:

  • fast 每次移动两步
  • slow 每次移动一步

-

1

2

3

4

5

6

fast

-

s1

-

s2

-

s3

slow

s1

s2

s3

-

-

-

s_i

表示指针移动是次数,可以发现 fast 移动到末尾时,slow 刚好在中点

代码语言:javascript
复制
/**
 * @param {ListNode} head
 * @return {TreeNode}
 */
var sortedListToBST = function (head) {
  return build(head, null)
  function build(left, right) {
    if (left === right) return null
    let mid = getMedian(left, right)
    let node = new TreeNode(mid.val)
    node.left = build(left, mid)
    node.right = build(mid.next, right)
    return node
  }

  function getMedian(left, right) {
    let fast = left,
      slow = left
    while (fast != right && fast.next != right) {
      fast = fast.next
      fast = fast.next
      slow = slow.next
    }
    return slow
  }
}

分治 + 中序遍历优化

上面两种方法:

  1. 将链表转换成数组,借用数组所有查询根节点
  2. 查找链表中心位,利用快慢指针查询链表中心位

可以假设链表有索引和长度属性(手动统计出来) 那么可以和数组一样,每次选择中点做根节点

使用方法 1 二分遍历链表,遇到节点就生成新的二叉树节点 (每个点开始都是独立的,指向他和他指向的节点都还没生产) 生产的二叉树节点的 left 子树与 right 子树通过递归依次生成

  • 递归参数(left,right),生成子树的区间
  • 递归结束,区间交错,说明区间的子元素遍历完了
代码语言:javascript
复制
/**
 * @param {ListNode} head
 * @return {TreeNode}
 */
var sortedListToBST = function (head) {
  let globalHead = head,
    len = getLength(head)
  return build(0, len - 1)

  function getLength(head) {
    let i = 0
    while (head != null) {
      ++i
      head = head.next
    }
    return i
  }

  function build(left, right) {
    if (left > right) return null
    let mid = parseInt((left + right + 1) / 2, 10)
    let node = new TreeNode()
    node.left = build(left, mid - 1)
    node.val = globalHead.val
    globalHead = globalHead.next
    node.right = build(mid + 1, right)
    return node
  }
}

[1]

题目:: https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree/

[2]

20200703:将有序数组转换为二叉搜索树 (难度:简单): ./../202007/20200703.md

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端小书童 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 示例
  • 抛砖引玉
    • 分治
      • 分治 + 中序遍历优化
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档