LeetCode – Convert Sorted List to Binary Search Tree (Java)

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

Thoughts

If you are given an array, the problem is quite straightforward. But things get a little more complicated when you have a singly linked list instead of an array. Now you no longer have random access to an element in O(1) time. Therefore, you need to create nodes bottom-up, and assign them to its parents. The bottom-up approach enables us to access the list in its order at the same time as creating nodes.

Java Solution

//  Definition for singly-linked list.
class ListNode {
	int val;
	ListNode next;
 
	ListNode(int x) {
		val = x;
		next = null;
	}
}
 
// Definition for binary tree
class TreeNode {
	int val;
	TreeNode left;
	TreeNode right;
 
	TreeNode(int x) {
		val = x;
	}
}
 
public class Solution {
	static ListNode h;
 
	public TreeNode sortedListToBST(ListNode head) {
		if (head == null)
			return null;
 
		h = head;
		int len = getLength(head);
		return sortedListToBST(0, len - 1);
	}
 
	// get list length
	public int getLength(ListNode head) {
		int len = 0;
		ListNode p = head;
 
		while (p != null) {
			len++;
			p = p.next;
		}
		return len;
	}
 
	// build tree bottom-up
	public TreeNode sortedListToBST(int start, int end) {
		if (start > end)
			return null;
 
		// mid
		int mid = (start + end) / 2;
 
		TreeNode left = sortedListToBST(start, mid - 1);
		TreeNode root = new TreeNode(h.val);
		h = h.next;
		TreeNode right = sortedListToBST(mid + 1, end);
 
		root.left = left;
		root.right = right;
 
		return root;
	}
}

16 thoughts on “LeetCode – Convert Sorted List to Binary Search Tree (Java)”

  1. other solution would be

    as we know #size of list,. we build just dummy binary tree, halfing size, and then do in-order traverse
    tree and list to change value for nodes.

  2. This version has smaller constants.

    class ListNode {
    ListNode next;
    int data;

    public ListNode(int data) {
    this.data = data;
    this.next = null;
    }
    };

    class TreeNode {
    TreeNode left;
    TreeNode right;
    int data;
    public TreeNode(int data) {
    this.data = data;
    this.left = null;
    this.right = null;
    }
    };

    public class sortedListToBalancedBST {
    public int getListLen(ListNode L) {
    ListNode n = L;
    if (n == null)
    return 0;

    int k = 1;
    while (n.next != null) {
    n = n.next;
    k++;
    }
    return k;
    }

    public ListNode getKthElement(ListNode L, int k) {
    if (L == null)
    return null;

    ListNode n = L;
    int i = 0;
    while (n.next != null && i < k) {
    n = n.next;
    i++;
    }
    return n;
    }

    public TreeNode do_BBST(ListNode L) {

    int len = getListLen(L);
    return build_BBST(L, len);
    }

    public TreeNode build_BBST(ListNode head, int len) {
    if (len == 0)
    return null;
    if (len == 1)
    return new TreeNode(head.data);

    int p = len / 2;
    ListNode pNode = getKthElement(head, p);

    TreeNode L = build_BBST(head, p);
    TreeNode R = build_BBST(pNode.next, len - p - 1);

    TreeNode n = new TreeNode(pNode.data);
    n.left = L;
    n.right = R;
    return n;
    }
    }

  3. public class Solution {
    public TreeNode sortedListToBST(ListNode head) {
    if (head == null) {
    return null;
    }
    ListNode end = head;
    while (end.next != null) {
    end = end.next;
    }
    return sortedListToBST(head, end);
    }
    public TreeNode sortedListToBST(ListNode head, ListNode end) {
    if (end.next == head) { //basically same ideas as start > end; occurs when one node left so head > midPrev and mid.next > end
    return null;
    }
    ListNode midPrev = findMidPrev(head, end);
    ListNode mid = midPrev.next;
    TreeNode node = new TreeNode(mid.val);
    node.left = sortedListToBST(head, midPrev);
    node.right = sortedListToBST(mid.next, end);

    return node;
    }
    //return node previous to mid
    public ListNode findMidPrev(ListNode head, ListNode end) {
    ListNode slowPrev = new ListNode(0);
    slowPrev.next = head;
    ListNode slow = head;
    ListNode fast = head;

    while (fast.next != end && fast != end && fast.next != null && fast != null) {
    slowPrev = slowPrev.next;
    slow = slow.next;
    fast = fast.next.next;
    }

    return slowPrev;
    }
    }

  4. For mid, your calculation would be better protected against overflow if it was this: int mid = start + (end-start)/2 ..Funny story, this was actually a bug in BST’s for a long time until someone found that it caused overflow. Hope this helps!
    Elegant solution otherwise!

  5. Hi. Can we put the input list as a member of first sortedListToBST function, and then pass it to second sortedListToBST function each time when calling it? If wo do it like this, and we move the pointer inside of sortedListToBST function, will this movement aware by caller? Thank you!

  6. def build_from_sorted_list(cls, start_node, end_node=None):
    if None == start_node:
    return None
    elif start_node is end_node:
    return cls(start_node.value)

    slow, fast = start_node, start_node
    while (end_node is not slow.next) and (end_node is not fast.next) and (end_node is not fast.next.next):
    slow = slow.next
    fast = fast.next.next

    node = cls(slow.value)
    node.left = cls.build_from_sorted_list(start_node, slow)
    node.right = cls.build_from_sorted_list(slow.next, end_node)

    return node

    recursive python version

  7. yes but the whole point of implementing it differently from arrays is list does not permit random access and we are accessing actual node data sequentially in this program!!

  8. Can we do the same without the static ListNode h
    Can we pass it as a parameter to the method sortedListtoBST?

  9. Hi.
    Do we need to use ceiling function to get the middle value?
    If the list is 1 -> 2 -> 3 -> 4 -> 5 -> 6, then the solution you provide would first get 3 not 4. (Using 4 as root would generate a good-looking tree).

Leave a Comment