
1. 分治算法+快慢指针
解题思路:时间复杂度O(
n
∗
l
o
g
2
n
n*log_2{n}
n∗log2n),空间复杂度O(
l
o
g
2
n
log_2{n}
log2n) |
---|
- 这种算法和108题的逻辑是一样的,都是每次找到一个中间结点作为根,来构造二叉树,可以先参考108题
- 但是108题的时间复杂度是O(n).这道题的时间复杂度是O(
n
∗
l
o
g
2
n
n*log_2{n}
n∗log2n)
- 因为108题是数组,而不是有序链表,数组是可以直接通过下标找到中间结点的
- 而这道题是链表,只能通过指针遍历找到中间结点。因为题目给的链表没有下标这一说。
- 而找到中间结点,经典做法就是快慢指针,快指针每次走两格,慢指针每次一格,当快指针到终点时,慢指针正好位于中间结点。

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 = getMedian(left, right);
TreeNode root = new TreeNode(mid.val);
root.left = buildTree(left, mid);
root.right = buildTree(mid.next, right);
return root;
}
public ListNode getMedian(ListNode left, ListNode right) {
ListNode fast = left,slow = left;
while (fast != right && fast.next != right) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
2. 分治+中序遍历优化
解题思路:时间复杂度O(n),空间复杂度O(
l
o
g
2
n
log_2{n}
log2n) |
---|
- 二叉搜索树的中序遍历结果就是一个升序序列,也就是说,题目给出的链表什么样子,二叉搜索树中序遍历结果就是什么样子
- 所以我们通过中序遍历构建二叉树结点,然后将链表中的值,依次填充到二叉树中,就完成了二叉树的创建
- 如何分治,构建空二叉树呢?
- 我们先获取链表长度,这样就可以二分了
- 然后根据二分规则构建一个二叉树框架
- 然后通过中序遍历的顺序,依次填充链表中的值到二叉树中。

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