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 都弄懂,會寫。 node
bst變double linked list。recursion秒了,而後第一個follow up是把雙鏈表變回去,要求balance。第二個follow up是在犧牲空間複雜度的狀況下如何優化時間,想了個時間O(n)的思路,面試
時間空間複雜度會分析優化