Difficulty: Medium

Related Topics: Linked List, Depth-first Search

Given the head of 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 1:

109. Convert Sorted List to Binary Search Tree - 图1

  1. Input: head = [-10,-3,0,5,9]
  2. Output: [0,-3,9,-10,null,5]
  3. Explanation: One possible answer is [0,-3,9,-10,null,5], which represents the shown height balanced BST.

Example 2:

  1. Input: head = []
  2. Output: []

Example 3:

  1. Input: head = [0]
  2. Output: [0]

Example 4:

  1. Input: head = [1,3]
  2. Output: [3,1]

Constraints:

  • The number of nodes in head is in the range [0, 2 * 10<sup>4</sup>].
  • -10^5 <= Node.val <= 10^5

Solution

Language: Java

  1. * ListNode(int val) { this.val = val; }
  2. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  3. * }
  4. */
  5. /**
  6. * Definition for a binary tree node.
  7. * public class TreeNode {
  8. * int val;
  9. * TreeNode left;
  10. * TreeNode right;
  11. * TreeNode() {}
  12. * TreeNode(int val) { this.val = val; }
  13. * TreeNode(int val, TreeNode left, TreeNode right) {
  14. * this.val = val;
  15. * this.left = left;
  16. * this.right = right;
  17. * }
  18. * }
  19. */
  20. class Solution {
  21. public TreeNode sortedListToBST(ListNode head) {
  22. return dfs(head, null);
  23. }
  24. /*
  25. 二分查找的步骤就是一颗 BST,所以可以使用二分查找来生成 BST
  26. NOTE: 通过二分查找生成的 BST 必定平衡的
  27. 二分查找有两种实现方法
  28. 1. https://en.wikipedia.org/wiki/Binary_search_algorithm#Procedure
  29. 2. https://en.wikipedia.org/wiki/Binary_search_algorithm#Alternative_procedure
  30. 这里使用第二种方法方便一些
  31. */
  32. private TreeNode dfs(ListNode lo, ListNode hi) {
  33. if (lo == hi) return null;
  34. ListNode mid = mid(lo, hi);
  35. TreeNode root = new TreeNode(mid.val);
  36. root.left = dfs(lo, mid);
  37. root.right = dfs(mid.next, hi);
  38. return root;
  39. }
  40. // 通过双指针技巧获得 mid 节点
  41. // slow 指针一次走一步
  42. // fast 指针一次走两步
  43. // 如果链表没有环的话,那么在 fast 走到终点时,slow 一定在中间
  44. private ListNode mid(ListNode node, ListNode last) {
  45. ListNode slow = node;
  46. ListNode fast = node;
  47. while(fast != last && fast.next != last) {
  48. slow = slow.next;
  49. fast = fast.next.next;
  50. }
  51. return slow;
  52. }
  53. }