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)的思路,
时间空间复杂度会分析