[leetcode每日一题2020/8/18]109. 有序链表转换二叉搜索树

有序链表转换二叉搜索树

  • 题目
  • 思路
  • 代码
    • 分治+先序遍历
    • 分治+中序遍历
  • 算法复杂度

题目来源于leetcode,解法和思路仅代表个人观点。传送门。
难度:中等
用时:忘了,应该不是很久,一开始还没想到【中序遍历】

题目

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

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

示例:

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

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

      0
     / \
   -3   9
   /   /
 -10  5

思路

一开始确实是想到【中序遍历】的思路生成树。但是想着想着,就变成【先序遍历】了。

每个的左边部分(比这个数小)都在他的左子树中,每个的右边部分(比这个数大)都在他的右子树中。


先序遍历的思路
那每次可以去这个数组的中间部分作为根节点,再对左半部分右半部分进行递归操作。
注意:由于给出的是【链表】,则需要把【链表】转换成数组,再操作。那么,时间复杂度至少都是O(n)了。


中序遍历的思路
对于【链表】,要是可以对树进行,从小到大进行插入,就可以实现了。
由于要求是平衡搜索树,那么,对于位置处于中间的结点比它小的数,和比它大的数(如果不考虑相等的情况),应该最多相差1个
那么,我们每次取,中间结点的,左半部分右半部分进行递归操作即可。
注意:由于要取【中间】结点,那么我们必须要知道链表的长度。那么,时间复杂度也至少O(n)。

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */

分治+先序遍历

class Solution {
    List<Integer> list = new ArrayList<>();
    public TreeNode sortedListToBST(ListNode head) {
        link2Array(head);
        TreeNode root = new TreeNode();
        TreeNode tree = insertNode(0,list.size()-1);
        return tree;
    }
    public TreeNode insertNode(int beg,int end){
        if(beg>end){
            return null;
        }
        int mid = (beg + end) / 2;
        TreeNode root = new TreeNode();
        root.val = list.get(mid);
        root.left = insertNode(beg,mid-1);
        root.right = insertNode(mid+1,end);

        return root;
    }
    public void link2Array(ListNode node){
        while(node!=null){
            list.add(node.val);
            node = node.next;
        }
    }
}

分治+中序遍历

(官方给出)

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;
    }
}

算法复杂度

时间复杂度: O(n)。其中n为链表的长度。每个结点遍历2遍。
空间复杂度: 先序遍历:O(n),n为结点数。中序遍历:O(logn),n为栈的最大深度。
先序遍历:
[leetcode每日一题2020/8/18]109. 有序链表转换二叉搜索树_第1张图片
中序遍历:
[leetcode每日一题2020/8/18]109. 有序链表转换二叉搜索树_第2张图片

你可能感兴趣的:(算法,leetcode)