Code Ganker: Convert Sorted List to Binary Search Tree -- LeetCode

2014年4月16日星期三

Convert Sorted List to Binary Search Tree -- LeetCode

原题链接: http://oj.leetcode.com/problems/convert-sorted-list-to-binary-search-tree/
这个题是二分查找树的题目,要把一个有序链表转换成一棵二分查找树。其实原理还是跟Convert Sorted Array to Binary Search Tree这道题相似,我们需要取中点作为当前函数的根。这里的问题是对于一个链表我们是不能常量时间访问它的中间元素的。这时候就要利用到树的中序遍历了,按照递归中序遍历的顺序对链表结点一个个进行访问,而我们要构造的二分查找树正是按照链表的顺序来的。思路就是先对左子树进行递归,然后将当前结点作为根,迭代到下一个链表结点,最后在递归求出右子树即可。整体过程就是一次中序遍历,时间复杂度是O(n),总的空间复杂度是栈空间O(logn)。代码如下:
public TreeNode sortedListToBST(ListNode head) {
    if(head == null)
        return null;
    ListNode cur = head;
    int count = 0;
    while(cur!=null)
    {
        cur = cur.next;
        count++;
    }
    ArrayList<ListNode> list = new ArrayList<ListNode>();
    list.add(head);
    return helper(list,0,count-1);
}
private TreeNode helper(ArrayList<ListNode> list, int l, int r)
{
    if(l>r)
        return null;
    int m = (l+r)/2;
    TreeNode left = helper(list,l,m-1);
    TreeNode root = new TreeNode(list.get(0).val);
    root.left = left;
    list.set(0,list.get(0).next);
    root.right = helper(list,m+1,r);
    return root;
}
这道题是不错的题目,不过这种构造的方式比较绕,因为一般来说我们都是对于存在的树进行遍历,这里是模拟一个中序遍历的过程把树从无到有地构造出来。过程比较不常规,不过多想想就明白了哈。

5 条评论:

  1. 这个是我的写法,就是扫描list找到middle node中点作为root,然后分别扫描左右两部分,分别找到左右两部分的中点作为左孩子和右孩子。如此反复。space 是O(1),time cost is O(n). 请教一下 这个时间复杂度是O(n)吧,我算了一下但是不敢肯定。谢谢
    public TreeNode sortedListToBST(ListNode head) {
    if (head == null)
    return null;
    return helper(head);
    } // end solution

    TreeNode helper(ListNode head) {
    // base case
    if (head == null)
    return null;
    if (head.next == null)
    return new TreeNode(head.val);

    ListNode pre = null;
    ListNode slow = head, fast = head;

    while(fast!=null && fast.next!=null){
    pre=slow;
    slow=slow.next;
    fast = fast.next.next;
    }
    pre.next=null;

    TreeNode root = new TreeNode(slow.val);
    TreeNode L = helper(head);
    TreeNode R = helper(slow.next);
    root.left = L;
    root.right = R;

    return root;
    } // end helper

    回复删除
    回复
    1. 此评论已被作者删除。

      删除
    2. 这种做法就是遍历一次树,然后每次遍历都要找中点,所以递推式是T(n) = 2T(n/2)+n/2,复杂度是O(nlogn),并不是O(n)的哈~ 空间因为递归需要栈,所以是O(logn)的~

      删除
  2. Hi, is it the time complexity T(n) = 2T(n/2)+n/2 ? That is O(nlogn). Thanks.

    回复删除
    回复
    1. Yes, you are right! I made a mistake. Thank you so much!

      删除