有序链表转化成搜索二叉树

Leetcode题目描述

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

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

示例:

给定的有序链表: [-10, -3, 0, 5, 9],

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

      0
     / 
   -3   9
   /   /
 -10  

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

分治思想解答

对于这类问题,基本上最容易想到的就是分治。因为有序链表和搜索二叉树有如下特性

  • 有序链表的中位数一定大于左侧的值,一定小于右侧的值
  • 搜索二叉树的根节点的值一定大于左子树的值,一定小于右子树的值
  • 平横二叉树的左右子树的高度差不超过1

结合以上三点,容易联想到获取链表的中位数的值,作为二叉树的根节点,然后依次递归构造左右子树的方法。难点在于如何寻找单链表的中位数和如何判断递归的终止条件。

寻找单链表的中位值不可如同数组索引一般的直接可以查询到中位值,可以通过快慢指针的方式获取。

  • 设定两个快慢指针,最初都指向单链表头节点的位置
  • 快指针走两步,而慢指针走一步,直到快指针指向尾部为止。此时慢指针所指向的位置就是中位数。

递归的终止条件应该是左节点等于右节点,分治的区间是左闭右开

分治demo

class Solution {
    public TreeNode sortedListToBST(ListNode head) {
        return buildTree(head, null);
    }

    public TreeNode buildTree(ListNode left, ListNode right) {
        if (left == right) {
            return null;
        }
        ListNode mid = getMedian(left, right);
        TreeNode root = new TreeNode(mid.val);
        root.left = buildTree(left, mid);
        root.right = buildTree(mid.next, right);
        return root;
    }

    public ListNode getMedian(ListNode left, ListNode right) {
        ListNode fast = left;
        ListNode slow = left;
        while (fast != right && fast.next != right) {
            fast = fast.next;
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

原文地址:https://www.cnblogs.com/Di-iD/p/13784845.html