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

【题目】*109. 有序链表转换二叉搜索树

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

示例:

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

      0
     / \
   -3   9
   /   /
 -10  5

【解题思路1】分治

将给定的有序链表转换为二叉搜索树的第一步是确定根节点。由于我们需要构造出平衡的二叉树,因此比较直观的想法是让根节点左子树中的节点个数与右子树中的节点个数尽可能接近

如何找出这样的一个根节点呢?我们可以找出链表元素的中位数作为根节点的值。找出链表中位数节点的方法多种多样,其中较为简单的一种是「快慢指针法」。在找出了中位数节点之后,我们将其作为当前根节点的元素,并递归地构造其左侧部分的链表对应的左子树,以及右侧部分的链表对应的右子树。
这里对于中位数的定义为:如果链表中的元素个数为奇数,那么唯一的中间值为中位数;如果元素个数为偶数,那么唯二的中间值都可以作为中位数,而不是常规定义中二者的平均值。

由于题目中给定的链表为单向链表,访问后继元素十分容易,但无法直接访问前驱元素。因此在找出链表的中位数节点 mid 之后,如果设定「左闭右开」的关系,就可以直接用 (left,mid) 以及 (mid.next,right) 来表示左右子树对应的列表了。并且,初始的列表也可以用 (head,null) 方便地进行表示,其中 null 表示空节点。

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 = getMid(left, right);
        TreeNode root = new TreeNode(mid.val);
        root.left = buildTree(left, mid);
        root.right = buildTree(mid.next, right);
        return root;
    }

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

【解题思路2】分治 + 中序遍历

设当前链表的左端点编号为 left,右端点编号为 right,包含关系为「双闭」,即 left 和 right 均包含在链表中。链表节点的编号为 [0,n)。中序遍历的顺序是「左子树 - 根节点 - 右子树」,那么在分治的过程中,我们不用急着找出链表的中位数节点,而是使用一个占位节点,等到中序遍历到该节点时,再填充它的值。

class Solution {
    
    
    ListNode globalHead;

    public TreeNode sortedListToBST(ListNode head) {
    
    
        globalHead = head;
        int length = getLength(head);
        return buildTree(0, length - 1);
    }

    public int getLength(ListNode head) {
    
    
        int ret = 0;
        while (head != null) {
    
    
            ++ret;
            head = head.next;
        }
        return ret;
    }

    public TreeNode buildTree(int left, int right) {
    
    
        if (left > right) {
    
    
            return null;
        }
        int mid = (left + right + 1) / 2;
        TreeNode root = new TreeNode();
        root.left = buildTree(left, mid - 1);
        root.val = globalHead.val;
        globalHead = globalHead.next;
        root.right = buildTree(mid + 1, right);
        return root;
    }
}

猜你喜欢

转载自blog.csdn.net/XunCiy/article/details/108070975