一、题目描述:109. 有序链表转换二叉搜索树(中等)
给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定的有序链表: [-10, -3, 0, 5, 9],
一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、解题思路
方法一、直接递归。
先遍历一次链表统计链表长度count,以及链表结尾。
1、每次递归寻找链表中间节点(如果是偶数,中间节点的后一位)作为树的根节点。如果链表要转换的个数为1则直接返回树根节点。递归为左边链表count/2个节点创建树,返回的树的节点作为当前树的左子树,递归为右边count/2(如果count为偶数,则count/2-1)个链表节点进行递归创建树,返回的树作为当前树的右子树。时间复杂度O(log(n))
方法二、
先遍历一遍链表,转换成数组,然后按方法一递归创建树,转成数组的好处是寻找中间节点时间复杂度O(1)。总的时间复杂度为O(n)
方法三、
模仿中序遍历
要思想是,因为我们知道题目给定的升序数组,其实就是二叉搜索树的中序遍历。那么我们完全可以按照这个顺序去为每个节点赋值。
实现的话,我们套用中序遍历的递归过程,并且将 start 和 end 作为递归参数,当 start == end 的时候,就返回 null。
三、代码
方法一、
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
ListNode * t = head;
int count = 1;
if (t == NULL)
return NULL;
while(t->next != NULL)
{
t = t->next;
count++;
}
TreeNode * tree = createTree(head,t,count);
return tree;
}
TreeNode * createTree(ListNode * head,ListNode * tail,int count)
{
if(count == 1 || head == tail)
{
TreeNode * root = new TreeNode(head->val);
return root;
}
int half = count/2;
ListNode * mid = head;
int count_t = 0;
while(count_t < half-1 && mid != tail)
{
mid = mid->next;
count_t ++;
}
ListNode * tail1 = mid;
mid = mid->next;
TreeNode * root = new TreeNode(mid->val);
TreeNode * left = createTree(head,tail1,half);
root->left = left;
if(mid == tail)
return root;
mid = mid->next;
if(count%2 == 0)
{
half = half -1;
}
TreeNode * right = createTree(mid,tail,half);
root->right = right;
return root;
}
};
方法二、代码
ListNode cur = null;
public TreeNode sortedListToBST(ListNode head) {
cur = head;
int end = 0;
while (head != null) {
end++;
head = head.next;
}
return sortedArrayToBSTHelper(0, end);
}
private TreeNode sortedArrayToBSTHelper(int start, int end) {
if (start == end) {
return null;
}
int mid = (start + end) >>> 1;
//遍历左子树并且将根节点返回
TreeNode left = sortedArrayToBSTHelper(start, mid);
//遍历当前根节点并进行赋值
TreeNode root = new TreeNode(cur.val);
root.left = left;
cur = cur.next; //指针后移,进行下一次的赋值
//遍历右子树并且将根节点返回
TreeNode right = sortedArrayToBSTHelper(mid + 1, end);
root.right = right;
return root;
}