leetcode题:109. 有序链表转换二叉搜索树(中等)

一、题目描述: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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值