【LeetCode每日一题】(8.18)有序链表转换二叉搜索树

有序链表转换二叉搜索树

给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

分治 + 中序遍历。

由于构造出的二叉搜索树的中序遍历结果就是链表本身,因此我们可以将分治和中序遍历结合起来,减少时间复杂度。

具体地,设当前链表的左端点编号为 left,右端点编号为 right,包含关系为「双闭」,即 left 和 right 均包含在链表中。链表节点的编号为 [0,n)。中序遍历的顺序是「左子树 - 根节点 - 右子树」,那么在分治的过程中,我们不用急着找出链表的中位数节点,而是使用一个占位节点,等到中序遍历到该节点时,再填充它的值。

我们可以通过计算编号范围来进行中序遍历:

中位数节点对应的编号为 mid=(left+right+1)/2;
编号为 (left+right)/2 的节点同样也可以是中位数节点。
左右子树对应的编号范围分别为 [left,mid−1][mid+1,right]

如果 left>right,那么遍历到的位置对应着一个空节点,否则对应着二叉搜索树中的一个节点。

这样一来,我们其实已经知道了这棵二叉搜索树的结构,并且题目给定了它的中序遍历结果,那么我们只要对其进行中序遍历,就可以还原出整棵二叉搜索树了。

代码实现

	int getLength(ListNode* head) {
        int ret = 0;
        for (; head != nullptr; ++ret, head = head->next);
        return ret;
    }

    TreeNode* buildTree(ListNode*& head, int left, int right) {
        if (left > right) {
            return nullptr;
        }
        int mid = (left + right + 1) / 2;
        TreeNode* root = new TreeNode();
        root->left = buildTree(head, left, mid - 1);
        root->val = head->val;
        head = head->next;
        root->right = buildTree(head, mid + 1, right);
        return root;
    }

    TreeNode* sortedListToBST(ListNode* head) {
        int length = getLength(head);
        return buildTree(head, 0, length - 1);
    }

猜你喜欢

转载自blog.csdn.net/qq_43762191/article/details/108074351
今日推荐