一、思路
給定一個單鏈表,其中的元素按升序排序,將其轉換爲高度平衡的二叉搜索樹。本題中,一個高度平衡二叉樹是指一個二叉樹每個節點的左右兩個子樹的高度差的絕對值不超過 1。舉例,
給定的有序鏈表: [-10, -3, 0, 5, 9],可能的樹的形態如下圖所示:
1.1 遞歸分析
遞歸三要素:終止條件、執行單元、返回值。其中執行單元是將待解決的問題由大化小的關鍵一步,即大規模變成小規模。就本題來說,BST的根結點一定是有序鏈表的中間元素,從首個元素到中間元素的前一個爲左子樹部分,從中間元素的後一個到結束爲右子樹部分。
遞歸函數的功能,給定有序鏈表的頭指針,建立與之相關的BST。要回答兩個問題:1)如何找到鏈表的中間元素——找到鏈表中間元素(當然只是近似的,與鏈表結點數是奇數還是偶數有關)。2)依次處理左子樹部分和右子樹部分。
TreeNode* sortedListToBST(ListNode* head) {
if (!head) return nullptr;
if (!head->next) return new TreeNode(head->val);
ListNode *slow = head, *slow_prev = nullptr, *fast = head;
while (fast && fast->next) {
slow_prev = slow;
slow = slow->next;
fast = fast->next->next;
}//slow最終指向鏈表中間元素
if (slow_prev) slow_prev->next = NULL; //斷開鏈表左側
TreeNode *root = new TreeNode(slow->val);
root->left = sortedListToBST(head);
root->right = sortedListToBST(slow->next);
return root;
}
1.2 中序遍歷
ListNode *current;
int findSize(ListNode *head) {
if (!head) return 0;
ListNode *current = head;
int num = 0;
while (current) { current = current->next; num++; }
return num;
}
TreeNode *convertListToBST(int begin, int end) {
if (begin > end) return nullptr;
int mid = begin + (end - begin) / 2;
TreeNode *tree_left = convertListToBST(begin, mid - 1);
TreeNode *root = new TreeNode(current->val);
root->left = tree_left;
current = current->next; //處理右半部分
root->right = convertListToBST(mid + 1, end);
return root;
}
TreeNode* sortedListToBST(ListNode* head) {
current = head;
return convertListToBST(0, findSize(head) - 1);
}