Medium
题目描述
给你一个二叉搜索树的根节点 root,返回一个 平衡的 二叉搜索树,新生成的树应该与原来的树有着相同的节点值。如果有多个构造方法,请你返回任意一种。
如果一个二叉搜索树中,每个节点的两个子树的深度差不超过 1,我们就称这个二叉搜索树是 平衡的。
示例 1:
输入:root = [1,null,2,null,3,null,4,null,null]
输出:[2,1,3,null,null,null,4]
解释:这不是唯一的正确答案,[3,1,4,null,2] 也是一个可行的构造方案。
示例 2:
输入:root = [2,1,3]
输出:[2,1,3]
提示:
- 树节点的数目在
[1, 10^4]范围内。 1 <= Node.val <= 10^5
解题思路
这道题的核心思路是先将二叉搜索树转换为有序数组,然后利用分治思想重新构造平衡的二叉搜索树。
解题步骤:
中序遍历获取有序数组:由于二叉搜索树的中序遍历结果是有序的,我们首先对原树进行中序遍历,将所有节点值存储在数组中。
分治构造平衡树:有了有序数组后,我们可以用分治的方法构造平衡二叉搜索树:
- 选择数组中间元素作为根节点
- 左半部分递归构造左子树
- 右半部分递归构造右子树
这样构造出的树保证是平衡的,因为我们每次都选择中间元素作为根,使得左右子树的节点数量差最多为1。
时间复杂度分析:
- 中序遍历:O(n)
- 构造新树:O(n)
- 总时间复杂度:O(n)
空间复杂度分析:
- 存储有序数组:O(n)
- 递归调用栈:O(log n)
- 总空间复杂度:O(n)
这是一个经典的"先解构再重构"的思路,充分利用了二叉搜索树的性质和分治思想。
代码实现
class Solution {
public:
TreeNode* balanceBST(TreeNode* root) {
vector<int> values;
inorder(root, values);
return buildBalancedBST(values, 0, values.size() - 1);
}
private:
void inorder(TreeNode* node, vector<int>& values) {
if (!node) return;
inorder(node->left, values);
values.push_back(node->val);
inorder(node->right, values);
}
TreeNode* buildBalancedBST(vector<int>& values, int left, int right) {
if (left > right) return nullptr;
int mid = left + (right - left) / 2;
TreeNode* root = new TreeNode(values[mid]);
root->left = buildBalancedBST(values, left, mid - 1);
root->right = buildBalancedBST(values, mid + 1, right);
return root;
}
};
class Solution:
def balanceBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
def inorder(node):
if not node:
return []
return inorder(node.left) + [node.val] + inorder(node.right)
def build_balanced_bst(values, left, right):
if left > right:
return None
mid = (left + right) // 2
root = TreeNode(values[mid])
root.left = build_balanced_bst(values, left, mid - 1)
root.right = build_balanced_bst(values, mid + 1, right)
return root
values = inorder(root)
return build_balanced_bst(values, 0, len(values) - 1)
public class Solution {
public TreeNode BalanceBST(TreeNode root) {
var values = new List<int>();
Inorder(root, values);
return BuildBalancedBST(values, 0, values.Count - 1);
}
private void Inorder(TreeNode node, List<int> values) {
if (node == null) return;
Inorder(node.left, values);
values.Add(node.val);
Inorder(node.right, values);
}
private TreeNode BuildBalancedBST(List<int> values, int left, int right) {
if (left > right) return null;
int mid = left + (right - left) / 2;
TreeNode root = new TreeNode(values[mid]);
root.left = BuildBalancedBST(values, left, mid - 1);
root.right = BuildBalancedBST(values, mid + 1, right);
return root;
}
}
var balanceBST = function(root) {
const inorder = (node, values) => {
if (!node) return;
inorder(node.left, values);
values.push(node.val);
inorder(node.right, values);
};
const buildBalancedBST = (values, left, right) => {
if (left > right) return null;
const mid = Math.floor((left + right) / 2);
const root = new TreeNode(values[mid]);
root.left = buildBalancedBST(values, left, mid - 1);
root.right = buildBalancedBST(values, mid + 1, right);
return root;
};
const values = [];
inorder(root, values);
return buildBalancedBST(values, 0, values.length - 1);
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 中序遍历O(n) + 构造新树O(n) |
| 空间复杂度 | O(n) | 存储有序数组O(n) + 递归栈O(log n) |