Convert Sorted List to Binary Search Tree (M)
题目
Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.
Example:
Given the sorted linked list: [-10,-3,0,5,9],
One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:
0
/
-3 9
/ /
-10 5
题意
将一个有序链表转换成左右子树高度差不超过1的平衡二叉查找树。
思路
比较简单的方法是,将链表中的值存入数组中,接下来与 108. Convert Sorted Array to Binary Search Tree 一样进行二分递归。
直接用快慢指针可以一次遍历找到链表中的中位数:初始时快慢指针同时指向头结点,每次移动慢指针走1步、快指针走2步,当快指针无法继续走时慢指针正好指在中位数处。每次找到当前链表的中位数作为当前子树的根,以中位数为中心划分出左右链表,递归生成左右子树。
模拟中序遍历:很玄妙,利用了二叉查找树的中序遍历是递增序列的性质,具体还是看官方解答 - Approach 3: Inorder Simulation。
代码实现
Java
快慢指针
class Solution {
public TreeNode sortedListToBST(ListNode head) {
if (head == null) {
return null;
}
ListNode mid = findMid(head);
TreeNode x = new TreeNode(mid.val);
x.left = mid == head ? null : sortedListToBST(head);
x.right = sortedListToBST(mid.next);
return x;
}
private ListNode findMid(ListNode head) {
ListNode pre = null;
ListNode slow = head, fast = head;
while (fast.next != null && fast.next.next != null) {
pre = slow;
slow = slow.next;
fast = fast.next.next;
}
if (pre != null) {
pre.next = null;
}
return slow;
}
}
模拟中序遍历
class Solution {
private ListNode head;
public TreeNode sortedListToBST(ListNode head) {
this.head = head;
// 求出链表长度
int len = 0;
ListNode p = head;
while (p != null) {
len++;
p = p.next;
}
return sortedListToBST(0, len - 1);
}
private TreeNode sortedListToBST(int left, int right) {
if (left > right) {
return null;
}
int mid = (left + right) / 2;
TreeNode leftChild = sortedListToBST(left, mid - 1);
TreeNode root = new TreeNode(head.val);
root.left = leftChild;
head = head.next;
root.right = sortedListToBST(mid + 1, right);
return root;
}
}
JavaScript
/**
* @param {ListNode} head
* @return {TreeNode}
*/
var sortedListToBST = function (head) {
const nums = []
while (head) {
nums.push(head.val)
head = head.next
}
return dfs(nums, 0, nums.length - 1)
}
var dfs = function (nums, left, right) {
if (left > right) return null
const mid = Math.trunc((right - left) / 2) + left
const root = new TreeNode(nums[mid])
root.left = dfs(nums, left, mid - 1)
root.right = dfs(nums, mid + 1, right)
return root
}