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

给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

方法一:数组存储+中序遍历

时间复杂度:O(n),用 O(1) 时间找到数组中间元素,总体复杂度相当于只遍历了一遍数组。
空间复杂度:O(n)。

  1. //1,转换为数组+中序遍历
  2. func sortedListToBST(head *ListNode) *TreeNode {
  3. arr := []int{}
  4. for head != nil {
  5. arr = append(arr, head.Val) //1,链表的值,全部转化为数组
  6. head = head.Next
  7. }
  8. return buildBST(arr, 0, len(arr)-1) //2,返回递归函数,参数为起止二叉树节点,0,len
  9. }
  10. func buildBST(arr []int, start, end int) *TreeNode {
  11. if start > end {
  12. return nil //3,递归结束条件
  13. }
  14. mid := (start + end) >> 1 //4,取中间值,防止溢出
  15. //mid := start + (end -start)/2
  16. root := &TreeNode{Val: arr[mid]} //5,中序遍历
  17. root.Left = buildBST(arr, start, mid-1)
  18. root.Right = buildBST(arr, mid +1 , end)
  19. return root
  20. }

方法二:快慢指针+递归

时间复杂度:根据递归式可知,T(n) = 2 * T(n / 2 ) + nO(nlog(n))。==On找中点,时间变长了。
空间复杂度:O(log(n))。==空间变小了

//递归+快慢指针
func sortedListToBST(head *ListNode) *TreeNode {
    if head == nil {
        return nil
    }

    slow, fast := head, head
    var prev *ListNode = nil 

    for fast != nil && fast.Next != nil {
        prev = slow
        slow = slow.Next
        fast = fast.Next.Next
    }

    root := &TreeNode{Val: slow.Val}    //1,父节点取中值

    if prev != nil {                    //2,从中点开始,递归左右子树
        prev.Next = nil
        root.Left = sortedListToBST(head)
    }
    root.Right = sortedListToBST(slow.Next)

    return root
}

方法三:从头中序遍历

  • 方法1每次获取数组中点花费O(1)O(1),方法2每次获取链表中点花费O(N)O(N),时间复杂度更高。
  • 能更快吗?直接获取头结点最快,不如直接构建它吧!它对应 BST 最左子树的根节点。
  • 于是我们先构建左子树,再构建根节点,再构建右子树。——遵循中序遍历。
  • 其实,BST 的中序遍历,打印的节点值正是这个有序链表的节点值顺序。
  • 如图,维护指针 h,从头结点开始,用 h.val 构建节点,构建一个,指针后移一位。

时间复杂度:O(n) == 时间没变
空间复杂度:O(logn) == 空间变小了

var tmp *ListNode

func sortedListToBST(head *ListNode) *TreeNode {
    if head == nil {
        return nil 
    }

    len_list := 0
    tmp = head
    for head != nil {
        len_list++
        head = head.Next
    }

    return buildBST(0, len_list - 1)    //找到建树的 左右范围
}


func buildBST(start, end int ) *TreeNode {
    if start > end {
        return nil
    }

    mid := (start + end) / 2
    left := buildBST(start,mid-1)

    root := &TreeNode{Val: tmp.Val}     //取到链表的值,作为父节点
    tmp = tmp.Next                     //链表依次向前进

    root.Left = left                    //因为是有序,中序构建树
    root.Right = buildBST(mid+1, end)

    return root
}