一、思路
给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。本题中,一个高度平衡二叉树是指一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 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);
}