题目
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 nullconst mid = Math.trunc((right - left) / 2) + leftconst root = new TreeNode(nums[mid])root.left = dfs(nums, left, mid - 1)root.right = dfs(nums, mid + 1, right)return root}
