Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
思路并不难。每次选链表的中间元素作为当前节点,左子树递归左半边链表,右子树递归右半边链表。如果这不是链表而是数组的话那么很简单了。但是这是链表,没有random access,因此需要写两个helper function来寻找中间元素以及中间元素之前的元素。
这里有很多地方容易出错,比如寻找mid的时候head, tail不能是null,head.val不能大于tail.val等。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; next = null; }
* }
*/
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode sortedListToBST(ListNode head) {
if(head == null)
return null;
ListNode tail = head;
while(tail.next != null)
tail = tail.next;
TreeNode root = recursive(head, head, tail);
return root;
}
public TreeNode recursive(ListNode head, ListNode start, ListNode end){
ListNode mid = findMid(start, end);
if(mid == null)
return null;
TreeNode newNode = new TreeNode(mid.val);
newNode.left = recursive(head, start, findPrevious(start, mid));
newNode.right = recursive(head, mid.next, end);
return newNode;
}
public ListNode findPrevious(ListNode head, ListNode node){
ListNode p = head;
if(p == null || p.val >= node.val)
return null;
while(p.next != node)
p = p.next;
return p;
}
public ListNode findMid(ListNode head, ListNode tail){
if(head == null || tail == null || head.val > tail.val)
return null;
if(head == tail)
return head;
ListNode slow = head;
ListNode fast = head;
while(fast.val != tail.val && fast.next.val != tail.val){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
更新:
上面的方法有点复杂了,毕竟list找中间元素不是很容易。其实可以这样想:一个BST的in order traversal就是一个有序的list,那么其实只要按照这个list来做一个in order traversal就可以了。有点拧,其实就是中序遍历。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; next = null; }
* }
*/
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode sortedListToBST(ListNode head) {
if(head == null)
return null;
//get the length of the list
int count = 0;
ListNode node = head;
while(node != null){
node = node.next;
count++;
}
ArrayList<ListNode> list = new ArrayList<ListNode>();
list.add(head);
return recur(list, 0, count - 1);
}
public TreeNode recur(ArrayList<ListNode> list, int start, int end){
if(start > end)
return null;
int mid = (start + end) / 2;
TreeNode left = recur(list, start, mid - 1);
//get the root node from the in order traversal
TreeNode root = new TreeNode(list.get(0).val);
root.left = left;
list.set(0, list.get(0).next);
root.right = recur(list, mid + 1, end);
return root;
}
}