【算法题解】64. 将二叉搜索树变平衡

这是一道 「中等难度」 的题
https://leetcode.cn/problems/balance-a-binary-search-tree/

题目

给你一棵 二叉搜索树,请你返回一棵 平衡后 的二叉搜索树,新生成的树应该与原来的树有着相同的节点值。如果有多种构造方法,请你返回任意一种。

如果一棵二叉搜索树中,每个节点的两棵子树高度差不超过 1 ,我们就称这棵二叉搜索树是 平衡的

示例 1:【算法题解】64. 将二叉搜索树变平衡

输入:root = [1,null,2,null,3,null,4,null,null] 
输出:[2,1,3,null,null,null,4] 
解释:这不是唯一的正确答案,[3,1,4,null,2,null,null] 也是一个可行的构造方案。 

示例 2:【算法题解】64. 将二叉搜索树变平衡

输入: root = [2,1,3] 
输出: [2,1,3] 

提示:

  • 树节点的数目在 范围内。

题解

这是一道 中等难度 的题,但是如果没有看清条件,直接上来就通过二叉树 旋转 来构建二叉平衡树,就会变成一道 困难 题。

注意题目给出的是 二叉搜索树 ,根据二叉搜索树的特性,其 中序遍历是一个有序序列

所以最简单的解法就是先求出二叉搜索树中序遍历序列,也就是一个有序序列,然后根据这个有序序列来构造二叉平衡树。

一、求中序序列

求中序遍历序列的方法见题解:【算法题解】41. 二叉树的中序遍历

由于题目给出的原始树是二叉搜索树,所以中序遍历最终会是一个有序序列,如示例一的中序序列为:[1, 2, 3, 4]

二、根据有序序列构造二叉平衡搜索树

我们将有序序列的开始和结束位置分别记为 startend

取序列的中间点 mid 构建根节点 root。剩余左右两边节点数要么相等,要么只相差 1 个,所以肯定是平衡的。

然后再用 mid 左边的子序列构造二叉平衡搜索树作为 root 的左子树。

同样的,使用 mid 右边的子序列构造一棵二叉平衡搜索树作为 root 的右子树。

构造左右子树都是本问题的子问题,使用 递归 的思路解题。

递归边界条件:当序列为空时,直接返回空即可。

求中间节点的时候,当总数是奇数的时候刚好可以取到中间点。当总数是偶数的时候(如总数是4),取中间位置前后的节点都可以(如示例一中的 2 或者 3),这里我们统一去前面的点,即 ;

代码实现

Java

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */

class Solution {
    private List<Integer> inorderList = new ArrayList<>();
    public TreeNode balanceBST(TreeNode root) {
        inorder(root);
        return buidBalanceBST(0, inorderList.size() - 1);
    }

    private void inorder(TreeNode node){
        if(node == null){
            return;
        }
        inorder(node.left);
        inorderList.add(node.val);
        inorder(node.right);
    }

    private TreeNode buidBalanceBST(int start, int end){
        if(start > end){
            return null;
        }

        int mid = (start + end) >> 1;
        TreeNode node = new TreeNode(inorderList.get(mid));
        node.left = buidBalanceBST(start, mid - 1);
        node.right = buidBalanceBST(mid + 1, end);

        return node;
    }

 

Go

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */

func balanceBST(root *TreeNode) *TreeNode {

    inorderList := []int{}

    var inorder func(node *TreeNode)

    inorder = func(node *TreeNode) {
        if node == nil {
            return
        }
        inorder(node.Left)
        inorderList = append(inorderList, node.Val)
        inorder(node.Right)
    }


    inorder(root)

    var buildBalanceBST func(start int, end int) *TreeNode 
    buildBalanceBST = func(start int, end int) *TreeNode {
        if start > end {
            return nil
        }

        mid := (start + end) / 2
        node := &TreeNode{inorderList[mid], nilnil}
        node.Left = buildBalanceBST(start, mid - 1)
        node.Right = buildBalanceBST(mid + 1, end)

        return node
    }

    return buildBalanceBST(0len(inorderList) - 1)
}

复杂度分析

时间复杂度,其中 N 为二叉树中的节点个数,二叉树的中序遍历时间复杂度为 ,构造二叉平衡树的时间复杂度也是 ,所以总体时间复杂度为 ,忽略常数后为

空间复杂度,其中 N 为二叉树中的节点个数,中序序列 inorderList 的最终长度为 N,空间复杂度为,求中序序列 inorderList 时的递归调用栈最大深度也是 N,空间复杂度为,所以总体来说空间复杂度还是

– End –

【算法题解】64. 将二叉搜索树变平衡

原文始发于微信公众号(i余数):【算法题解】64. 将二叉搜索树变平衡

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/193554.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!