欢迎访问LeetCode题解合集
题目描述
给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定的有序链表: [-10, -3, 0, 5, 9],
一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
题解:
法一:
参考 将有序数组转换为二叉搜索树 ,不过这题换成 链表 ,我们可以考虑使用哈希表将链表中的值和下标对应起来。
时间复杂度:$O(n)$
额外空间复杂度:$O(n)$
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<int, int> hash;
void build( TreeNode*& root, int l, int r ) {
if ( l > r ) return;
int m = (l + r) >> 1;
root = new TreeNode(hash[m]);
build( root->left, l, m - 1 );
build( root->right, m + 1, r );
}
TreeNode* sortedListToBST(ListNode* head) {
int k = 0;
ListNode *p = head;
while ( p ) {
hash[k++] = p->val;
p = p->next;
}
TreeNode *root = nullptr;
build ( root, 0, k - 1 );
return root;
}
};
/*
时间:36ms,击败:88.09%
内存:31.4MB,击败:69.51%
*/
法二:
不使用哈希表,在递归建树过程中使用快慢指针找到中间节点。
时间复杂度:$O(nlogn)$
额外空间复杂度:$O(logn)$
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<int, int> hash;
void build( TreeNode*& root, ListNode*& left, ListNode* right ) {
if ( left == right ) return;
ListNode *fast = left, *slow = left;
while ( fast != right && fast->next != right ) {
fast = fast->next->next;
slow = slow->next;
}
root = new TreeNode(slow->val);
build( root->left, left, slow );
build( root->right, slow->next, right );
}
TreeNode* sortedListToBST(ListNode* head) {
TreeNode *root = nullptr;
build ( root, head, nullptr );
return root;
}
};
/*
时间:36ms,击败:88.09%
内存:27.8MB,击败:99.90%
*/
法三:
法一的优化,法一使用哈希表的原因是寻找中位数节点较为困难。
由于中序遍历的结果就是链表本身,于是没必要使用哈希表。可以考虑在中序遍历时先将根节点设为一个占位符,只分配内存空间,不设置具体值,再次回到根节点时设置值(保证head一直在移动)。
时间复杂度:$O(n)$
额外空间复杂度:$O(logn)$
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<int, int> hash;
void build( TreeNode*& root, ListNode*& head, int l, int r ) {
if ( l > r ) return;
int m = (l + r) >> 1;
root = new TreeNode();
build( root->left, head, l, m - 1 );
root->val = head->val;
head = head->next;
build( root->right, head, m + 1, r );
}
TreeNode* sortedListToBST(ListNode* head) {
int n = 0;
ListNode *p;
for ( p = head; p; p = p->next, ++n );
TreeNode *root = nullptr;
build ( root, head, 0, n - 1 );
return root;
}
};
/*
时间:24ms,击败:99.75%
内存:27.8MB,击败:99.95%
*/