1. Slow & Fast Pointers Midpoint Divide-and-Conquer
Intuition
At each step, use two pointers (slow and fast) to find the midpoint of the current list segment. Create a tree node with slow.val. Disconnect the left half from slow (or pass boundaries), then recursively call the function on the left half and right half (slow.next). Because finding the middle takes O(L) time at each level and there are O(log N) levels, the total time is O(N log N).
When to apply: When understanding the natural extension of the array divide-and-conquer algorithm to linked lists.
Algorithm
- Find the middle of the linked list using slow and fast pointers at each recursive level, disconnect or bound the list, and recurse on halves.
#include <iostream> struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {}}; struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}}; class Solution {public: TreeNode* sortedListToBST(ListNode* head) { if (!head) return nullptr; if (!head->next) return new TreeNode(head->val); ListNode* prev = nullptr; ListNode* slow = head; ListNode* fast = head; while (fast && fast->next) { prev = slow; slow = slow->next; fast = fast->next->next; } // Disconnect left half if (prev) prev->next = nullptr; TreeNode* root = new TreeNode(slow->val); root->left = sortedListToBST(head); root->right = sortedListToBST(slow->next); return root; }}; int main() { // Construct [-10, -3, 0, 5, 9] ListNode* head = new ListNode(-10); head->next = new ListNode(-3); head->next->next = new ListNode(0); head->next->next->next = new ListNode(5); head->next->next->next->next = new ListNode(9); Solution sol; TreeNode* root = sol.sortedListToBST(head); std::cout << "Root: " << root->val << " (Left: " << root->left->val << ", Right: " << root->right->val << ")" << std::endl; return 0;}Time & Space Complexity
- Time complexity:
O(N log N) - Space complexity:
O(log N) stack frames