[LeetCode題解]109. 有序連結串列轉換二叉搜尋樹 | 快慢指標 + 遞迴
阿新 • • 發佈:2020-11-20
題目描述
給定一個單鏈表,其中的元素按升序排序,將其轉換為高度平衡的二叉搜尋樹。
本題中,一個高度平衡二叉樹是指一個二叉樹每個節點的左右兩個子樹的高度差的絕對值不超過 1。
示例:
給定的有序連結串列: [-10, -3, 0, 5, 9],
一個可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面這個高度平衡二叉搜尋樹:
0
/ \
-3 9
/ /
-10 5
解題思路
題目說給定的單鏈表是有序的,要轉換為高度平衡的二叉搜尋樹,也就是說這個連結串列是樹的前序遍歷。
因此思路就轉為:找到連結串列的中間節點,然後以此節點把連結串列一分為二,作為左右子樹的範圍。
使用快慢指標+遞迴
- 通過快慢指標為到連結串列的中間節點。
- 通過遞迴來構成節點的左右子樹。
- 遞迴結束條件是連結串列為空時連結串列只有一個元素時返回其本身,即
head
;
程式碼
/** * Definition for singly-linked list. * public class ListNode { * public int val; * public ListNode next; * public ListNode(int val=0, ListNode next=null) { * this.val = val; * this.next = next; * } * } */ /** * Definition for a binary tree node. * public class TreeNode { * public int val; * public TreeNode left; * public TreeNode right; * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { * this.val = val; * this.left = left; * this.right = right; * } * } */ public class Solution { public TreeNode SortedListToBST(ListNode head) { // 快慢指標:先找到中間節點,然後左右兩邊的連結串列作為左右子樹,直到連結串列只有一個節點。 if(head == null || head.next == null) { return head; } ListNode fast = head, slow = head, pre = null; while(fast != null && fast.next != null) { fast = fast.next.next; pre = slow; slow = slow.next; } TreeNode root = new TreeNode(slow.val); pre.next = null; // 把連結串列一分為二 root.left = SortedListToBST(head); root.right = SortedListToBST(slow.next); return root; } }
複雜度分析
- 時間複雜度:\(O(nlogn)\),其中 \(n\) 是連結串列長度。
- 空間複雜度:\(O(1)\)。