# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def sortedListToBST(self, head: ListNode) -> TreeNode:
def find_middle(start, end):
slow = fast = start
while fast != end and fast.next != end:
slow = slow.next
fast = fast.next.next
return slow
def convert(start, end):
if start == end:
return None
mid = find_middle(start, end)
node = TreeNode(mid.val)
node.left = convert(start, mid)
node.right = convert(mid.next, end)
return node
return convert(head, None)
// Definition for singly-linked list.
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
return convert(head, nullptr);
}
private:
TreeNode* convert(ListNode* start, ListNode* end) {
if (start == end) return nullptr;
ListNode* mid = findMiddle(start, end);
TreeNode* node = new TreeNode(mid->val);
node->left = convert(start, mid);
node->right = convert(mid->next, end);
return node;
}
ListNode* findMiddle(ListNode* start, ListNode* end) {
ListNode* slow = start;
ListNode* fast = start;
while (fast != end && fast->next != end) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
};
// Definition for singly-linked list.
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
// Definition for a binary tree node.
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
public TreeNode sortedListToBST(ListNode head) {
return convert(head, null);
}
private TreeNode convert(ListNode start, ListNode end) {
if (start == end) return null;
ListNode mid = findMiddle(start, end);
TreeNode node = new TreeNode(mid.val);
node.left = convert(start, mid);
node.right = convert(mid.next, end);
return node;
}
private ListNode findMiddle(ListNode start, ListNode end) {
ListNode slow = start;
ListNode fast = start;
while (fast != end && fast.next != end) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {ListNode} head
* @return {TreeNode}
*/
var sortedListToBST = function(head) {
function findMiddle(start, end) {
let slow = start, fast = start;
while (fast !== end && fast.next !== end) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
function convert(start, end) {
if (start === end) return null;
let mid = findMiddle(start, end);
let node = new TreeNode(mid.val);
node.left = convert(start, mid);
node.right = convert(mid.next, end);
return node;
}
return convert(head, null);
};
Given the head of a singly linked list head
where the elements are sorted in ascending order, your task is to convert it into a height-balanced binary search tree (BST).
A height-balanced BST is defined as a binary tree in which the depth of the two subtrees of every node never differs by more than one.
The main challenge is to convert a sorted sequence (in the form of a singly linked list) into a balanced BST. If the input were an array, we could easily pick the middle element as the root and recursively build the left and right subtrees. However, since the input is a singly linked list, we cannot access the middle element in constant time.
A brute-force approach would be to convert the list into an array, then use the array-to-BST method. But this uses extra space. To optimize, we look for a way to find the middle of the list in-place (using slow and fast pointers), allowing us to recursively construct the BST without extra storage.
The key insight is to use the slow and fast pointer technique to find the middle node of any sublist, which will serve as the root of the (sub)tree. We then recursively build the left and right subtrees from the left and right parts of the list.
slow
and fast
.slow
moves one step at a time, fast
moves two steps.fast
reaches the end, slow
will be at the middle node.null
(no nodes to process).start
and end
pointers to delimit the current sublist.start
to mid
.mid.next
to end
.
Input: head = [-10, -3, 0, 5, 9]
0
(slow/fast pointer technique)0
becomes root[-10, -3]
-10
(slow at -10, fast at -3)-10
becomes left child-3
(becomes right child of -10)[5, 9]
9
(slow at 5, fast at 9)9
becomes right child5
(becomes left child of 9)0 / \ -10 9 \ / -3 5
To convert a sorted singly linked list to a height-balanced BST, we use the slow/fast pointer technique to find the middle node, recursively building the tree by always choosing the middle as the root. This ensures the BST is balanced. The approach is elegant because it avoids extra space and leverages linked list traversal, though it does have O(N log N) time complexity. Understanding this recursive, divide-and-conquer method is key to tackling many similar problems involving sorted data and balanced trees.