NO.109 将有序链表转换为二叉搜索树 中等
思路一:中序遍历还原 这道题和NO.108属于姊妹题,同样是通过明确的遍历序列还原二叉树。
所以说可以使用相同的思路,中点确定根,从而确定左右子树,递归出口也是区间内没有元素。
本题的难点在于参数是一个链表,不能像数组一样随机访问。
找链表最笨的方法就是两次遍历,第一次算节点个数,第二次找到中点。
通常这样的问题都可以使用快慢指针来解决,快指针一次走两步,慢指针一次走一步,当快指针走完区间,慢指针就刚好到达区间的1/2处。
1 2 3 4 5 6
| ListNode fast = head, slow = head; while (fast != tail && fast.next != tail) { fast = fast.next.next; slow = slow.next; }
|
PS:本题递归函数传参形成的区间是前闭后开的,所以左右端点相等就表示区间内没有元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public TreeNode sortedListToBST(ListNode head) { if (head == null) return null; return buildBST(head, null); }
private TreeNode buildBST(ListNode head, ListNode tail) { if (head == tail) return null; ListNode fast = head, slow = head; while (fast != tail && fast.next != tail) { fast = fast.next.next; slow = slow.next; } TreeNode root = new TreeNode(slow.val); root.left = buildBST(head, slow); root.right = buildBST(slow.next, tail); return root; }
|
时间复杂度:O(nlogn) 每个元素需要访问一次生成树节点,每次生成树节点的时候都需要快慢指针找中点是个O(logn)。
本人菜鸟,有错误请告知,感激不尽!
更多题解和源码:github