LeetCode 109 有序链表转换成二叉搜索树

本文介绍了如何将有序链表转换为二叉搜索树,采用快慢指针找到链表中心,然后递归构建子树。通过LeetCode 109题目的解题过程,探讨了这种方法的效率和朴素之美。
摘要由CSDN通过智能技术生成

相比于LeetCode 108 , 这道题变成了中等难度的题目, 在 107 中, 我使用的是以中心点作为分割, 然后数组左右两部分分别作为左子树和右子树去进行递归, 这道题我也打算使用这个思路, 步骤为:

1. 找到链表的中心位置.

2. 构造子树

3. 递归

 

问题在于如何找到链表的中心节点?

LeetCode 前面的有关于链表的题目, 经常是会使用"快慢指针"的方法:

   快指针一次步进2个节点, 慢指针一次步进1个节点,这样当快指针到达终点的时候,慢指针所指向的节点就是中间的节点.

 

题目假设的是, 升序链表. 也就意味着不可能有环? 严格来说, 所有元素相同的情况下,构成一个环, 也可以算是"升序链表"吧,看起来有点不严谨, 不过不深究了. 最好还是 快慢指针 也可以同时检查有没有环.

 

最后写出来的算法是这样的

def sortedListToBST(head: ListNode): TreeNode = {

    def middle(from:ListNode, until: ListNode):ListNode = {
      if(from == null || (from eq until)) null
      else {
        var i = from
        var j = from
        var end = false
        while(!(j.next eq until) && !end) {
          i = i.next
          j = j.next
          if(j != null && !(j.next eq until)){
            j = j.next
          } else end = true
        }
        i
      }
    }


    def buildTree(from: ListNode, until: ListNode): TreeNode = {
      if(from == null) null
      else if(from.next eq until) new TreeNode(from.x)
      else {
        val middleNode = middle(from, until)
        if(middleNode == null) {
          null
        } else {
          val tNode = new TreeNode(middleNode.x)
          tNode.left = buildTree(from,middleNode)//使用 until的好处在于此, 左半边不需要知道上一个节点
          tNode.right = buildTree(middleNode.next,until)
          tNode
        }
      }
    }

    if(head == null) null
    else buildTree(head, null)
  }

居然没有我大Scala的语法高亮, ╭(╯^╰)╮

其中middle函数是用来计算中间节点的

buildTree函数用来进行递归

平常的递归实现的话, 我比较喜欢使用 from, to 的下标, 后者是包含在内部的, 总觉得思考起来比较方便, 但是这次的话,使用until会比较好, 因为使用 to 的话, 还需要找到上一个节点, 这里不方便.

虽然这个算法可以通过, 但是不是很高效, 因为每次都要遍历去寻找中心节点, 相当于应该遍历 n( 1 + 1/2 + 1/4 + ...) 次(不超过2次)

但是思想却很朴素, 递归思想, 不搞花里胡哨的, 看起来还是美的呀.

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值