leetcode 109 根据有序链表转成二叉树

71 阅读2分钟

该题是一道根据一个有序链表构造一个BST(搜索二叉树),题目难点就是定位根节点,如果理解了这一点那么这一题就不会太难弄了。

思路:

  • 把链表转换为数组,就可以根据数组的下标,灵活的得到每一个根节点的位置进行分治。
    public TreeNode sortedListToBST(ListNode head) {
        List<Integer> list = new ArrayList<>();
        while(head != null){
            list.add(head.val);
            head = head.next;
        }
//        String[] strings = list.toArray(new String[0]);
        Integer[] ints = list.toArray(new Integer[0]);
        return DFS(0,ints.length-1,ints);
    }
    private TreeNode DFS(int start,int end,Integer[] ints){
        if (start > end) return null;
        int mid = start+(end - start)/2;
        TreeNode treeNode = new TreeNode(mid);
        treeNode.left = DFS(start,mid-1,ints);
        treeNode.right = DFS(mid+1,end,ints);
        return treeNode;
    }

注意:因为我需要把链表转换到数组,根据数组必须先给出容量,所以使用list集合进行一个载体承载,最后调用toArray()方法将其转变为数组,需要转换成什么数组只需要传入参数 new T[0]即可转换,不可以传入int因为是引用类型。但是说实话,这样的办法并不好,因为Integr相对于int类型要大一些,可能就会导致时间复杂度以及空间复杂度更差,最好还是自己写一个for循环进行转变为int或者就直接使用list集合,如果用什么其它的更好的方法也是可以的。这种链表转为数组的做法,本身就是一个投机取巧的方法,且时间复杂度以及空间复杂度很不理想。建议不要太多使用。

  • 可以使用快慢指针,使用快指针走两步,慢指针走一步的方式,直到快指针走到最后一步,那么慢指针就走到这一条链表中的树的根节点的位置。
public TreeNode sortedListToBST(ListNode head) {
    if (head == null) return null;
    if (head.next == null) return new TreeNode(head.val);
    ListNode slow = head;
    ListNode fast = head;
    ListNode pre = head;
    while(fast != null && fast.next !=null){
        pre = slow;
        slow = slow.next;
        fast = fast.next.next;
    }
    pre.next = null;
    TreeNode treeNode = new TreeNode(slow.val);
    treeNode.left = sortedListToBST(head);
    treeNode.right = sortedListToBST(slow.next);
    return treeNode;
}

注意:需要考虑一些特殊情况,比如到listnode只有一个结点时(会进入不了while循环一直使用head进入下一层),就应该 直接返回这个结点所做成的结点,避免一直进入递归而导致内存耗尽异常。还有一定要写好递归终止条件当结点为空时就直接返回null,避免空指针异常。