109.有序链表转换二叉搜索树
题意:
给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定的有序链表: [-10, -3, 0, 5, 9],一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
解题思路:
其实解题思路比较简单,就是每次找链表的中值就是根节点,然后划分链表为左右两棵子树然后继续递归求解,但是在实现的过程中能够进行一些优化,比较粗暴的实现就是用list存链表,然后每次递归的时候从list里面找中值
java实现-List转存链表查找中值
public List<Integer> list;
public TreeNode buildTree(int left,int right){
if(left>right) return null;
int mid = (left+right+1) / 2;
TreeNode cur = new TreeNode(list.get(mid));
//System.out.println(cur.val);
cur.left = buildTree(left,mid-1);
cur.right = buildTree(mid+1,right);
return cur;
}
public TreeNode sortedListToBST(ListNode head) {
list = new ArrayList<Integer>(); //还是用list存吧
while(head!=null){
list.add(head.val);
head = head.next;
}
return buildTree(0,list.size()-1);
}
但是使用List存链表无可避免有一个O(N)的遍历操作,对此进行优化的话,可能考虑使用快慢指针查找单链表的中值,但是在查找到中值之后对左子树进行递归的时候,需要删除右子树上的节点,所以需要一个pre_mid
指针,指向中值节点的上一个节点,在递归左子树之前把其next指针置为空,即pre_mid.next=null
java实现-快慢指针-前驱指针
public ListNode midItem(ListNode head){
if(head==null) return null;
ListNode pre = null;
ListNode fast = head;
while(fast!=null&&fast.next!=null){//快慢指针的循环条件的问题
pre = head;
head = head.next;
fast = fast.next.next;
}
return pre;
}
public TreeNode sortedListToBST(ListNode head) {
//快慢指针找中点
if(head==null) return null;
ListNode pre_mid = midItem(head);
ListNode mid = pre_mid==null? head:pre_mid.next;
TreeNode cur = new TreeNode(mid.val);
if(pre_mid!=null){
pre_mid.next = null;
cur.left = sortedListToBST(head);
}
cur.right = sortedListToBST(mid.next);
return cur;
}
查看题解发现还有一种利用中序遍历二叉搜索树的特性进行递归优化实现的方式,也比较巧妙,首先对链表求长度,然后可以按照长度进行递归了,然后再中序的位置上对节点进行赋值,此时的数据变化就是链表的顺序
java实现-中序优化
public ListNode listnode;
public TreeNode buildTree(int left,int right){
if(left>right) return null;
int mid = (left+right+1) / 2;
TreeNode cur = new TreeNode();
//System.out.println(cur.val);
cur.left = buildTree(left,mid-1);
cur.val = listnode.val;//中序的位置上设置值
listnode = listnode.next; //更新到链表的下一个值
cur.right = buildTree(mid+1,right);
return cur;
}
//和中序遍历结合起来
public TreeNode sortedListToBST(ListNode head) {
int len = 0;
listnode = head;
while(head!=null){
len++;
head = head.next;
}
return buildTree(0,len-1);