Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
看到这题我想到的直接的做法是每次找到链表的中间结点(slow 和 fast双指针屡试不爽),递归构建左子树和右子树。 但是注意这里需要分割左子树,则需要将左子序列的尾结点的next置为None,否则又会出现环。所以这种情况下,每次找到中序结点的前一个结点更明智。当然如果只有一个或者两个结点,只能找到头结点,所以需要判断。这种做法避免了再开一个指针来做尾结点的处理。这种每次处理都需要花费O(n)的时间复杂度来寻找中间结点,所以时间复杂度为O(nlogn),空间复杂度也为O(nlogn),代码如下:
class Solution(object): def sortedListToBST(self, head): """ :type head: ListNode :rtype: TreeNode """ if not head: return None if not head.next: return TreeNode(head.val) slow = head fast = head.next while fast.next and fast.next.next: fast = fast.next.next slow = slow.next if slow == head and not slow.next.next: #判断是不是只有两个节点的情况 root = TreeNode(slow.val) root.right = self.sortedListToBST(slow.next) #此时只有右子树 else: root = TreeNode(slow.next.val) tmp = slow.next slow.next = None root.left = self.sortedListToBST(head) root.right = self.sortedListToBST(tmp.next) return root
以上解法是top down,如果采取bottom up的做法,可以将时间复杂度降为O(n)。看了一下bottom up的做法都参考自一个leetcode的链接:http://articles.leetcode.com/convert-sorted-list-to-balanced-binary 这种做法每次在递归的时候会改头结点。所以当返回时建立的树结点就是当前的子树的根结点。代码如下:
class Solution(object): def sortedListToBST(self, head): """ :type head: ListNode :rtype: TreeNode """ if not head: return None cur = head n = 0 while cur: cur = cur.next n += 1 return self.helper([head], 0, n-1) def helper(self, head, start, end): if start > end: return None mid = start + (end - start)/2 left = self.helper(head, start, mid-1) parent = TreeNode(head[0].val) head[0] = head[0].next parent.left = left parent.right = self.helper(head, mid+1, end) return parent
这段代码还没有理解的特别透彻,但是为了使输入的头结点可以更改,需要使用list来传递参数。