Convert Sorted double linked  List to Binary Search Tree
In place

闫老师讲的这两个 答案 是把他 看成 single linked list了, 但是对于double linked list , 也适用






base case : at least three nodes , other wise mid.next and mid.next.next NPE


NOT TESTED YET 

小班文档


Solution one:

先处理 head.next =null
And head.next.next = null


闫老师也不是一上来就知道怎么做, 也是从 induction 做, 把general 的 case 处理掉
然后再回头看 base case ,分别从 size = 0, 1,2, 3 看起, 有没有越界, 之类的

是一步步分析出来的。 

现在做tag和 面经题, 也是要自己一步步分析出来, 面试的时候 靠的是之前准备时的功底, 不是
当场现想,或者无脑背答案






// one is list node . Another one Is tree node 




Draw the recursion tree
N  find the middle node on each level in total. There is logn levels 
  So   O(NLOGN) in total 

 

class Solution {
    public TreeNode ddlToBST(ListNode head) {
      // base case 
      if(head == null) return null;
      if(head.next == null) return ..;
      if(head.next.next == null) return ..;
      
      // recursion + induction rule
      ListNode mid = findMiddle(head);
      TreeNode root = new TreeNode(mid.next.val);
      ListNode next = mid.next.next;
      mid.next.next = null;
      mid.next = null;
      root.left = ddlToBST(head);
      root.right = ddlToBST(next);
      return root;
    }
}




Solution two:
一边构建 left subtree 一边对这个linked list 进行 
遍历

time: o(n)





Convert Sorted double linked  List to Binary Search Tree
In place
还是不理解这个做法

Solution two:
一边构建 left subtree 一边对这个linked list 进行 
遍历

time: O(n)

// get the length of the list 
public TreeNode (ListNode head){
  int length = length(head);
  
  // construct the tree recursively
  return construct(0, length - 1);
}

ListNode curInOrder = head;
private TreeNode construct(int start, int end){
  // base case
  if(start > end) return null;
  
  int mid = start + (end - start) / 2;
  TreeNode left = construct(start, mid - 1);
  TreeNode root = new TreeNode(curInOrder.val);
  
  curInOrder = curInOrder.next;
  root.left = left;
  
  root.right = construct(mid + 1, end);
  return root;
 
}

private int length(ListNode head){
  int count = 0;
  ListNode pointer = head;
  while(pointer != null){
    count +=1;
    pointer = pointer.next;
  }
  return count;
}




///////
自己写的 solution 1 

// later I can test my code using this node class, and treat tree node and list node as the same 
class Node {
    public int val;
    public Node left;
    public Node right;

    public Node() {}

    public Node(int _val,Node _left,Node _right) {
        val = _val;
        left = _left;
        right = _right;
    }
}










public TreeNode dllToBST(ListNode head){
  // base case. when the size of the linked list is 0, 1, 2 
  // when the size is 0
  if(head == null){
    return null;
  }
  
  // when the size is 1
  if(head.next = null){
    return new TreeNode(head.val);
  }
  
  // when the size of the linked list is 2 
  if(head.next.next = null){
    TreeNode next = new TreeNode(head.next.val);
    TreeNode root = new TreeNode(head.val);
    root.right = next;
    return root;
  }
  
  // recursion + induction
  ListNode middle = findMid(head);
  TreeNode root = new TreeNode(middle.val);
  ListNode next = middle.next;
  ListNode prev = middle.prev;
  
  middle.next = null;
  prev.next = null;
  
  root.left = dllToBST(head);
  root.right = dllToBST(next);
  
  return root;
}


private ListNode findMid(ListNode head){
  // base case : 0 1 2 3 
  // size 0, 1, 2 wont be here because they have taken care of 
  // in the base case of the above func
  ListNode tail = head.prev;
  
  ListNode fast = head;
  ListNode slow = head;
  
  while(fast != tail && fast.next != tail){
    fast = fast.next.next;
    slow = slow.next;
  }
  
  return slow;
}

 把自己写的solution 1 和 闫老师写的solution2 都弄懂,会写。 

bst变double linked list。recursion秒了,然后第一个follow up是把双链表变回去,要求balance。第二个follow up是在牺牲空间复杂度的情况下如何优化时间,想了个时间O(n)的思路,

时间空间复杂度会分析