参考: 我被问到这个问题@MS SDE采访,第3轮。这不是一个家庭作业问题。我也考虑了一下,并在下面提到我的方法。
问题: 修改BST以使其尽可能平衡。不用说,你应该尽可能高效。
提示:
采访者说这是一个合乎逻辑的问题,如果你有不同的想法,你会得到答案。没有困难的编码。
- >话虽如此,我认为他不指望我指向AVL / RB树。
我的解决方案: 我建议,我会按顺序遍历树,把中间元素作为新树的根(让我们称之为新的根)。然后转到中间元素的左侧部分,将其中间元素作为树根新子根的左子树的根。同样适用于正确的部分。 递归执行此操作将提供最佳的平衡BST。
我为什么要在此发帖: 但他对答案并不满意:(那么,真的有一种方法可以做这个没有用于权重/ RB着色策略,还是他只是在骗我? 请加入你的专家意见。
重复?不!的 我知道有这个question但是请求者提出的解决方案太复杂了,其他人讨论了AVL树。
答案 0 :(得分:38)
您可能需要查看 Day-Stout-Warren 算法,该算法是一种O(n)-time,O(1)空间算法,用于将任意二进制搜索树重新整形为完整的二叉树。直觉上,该算法的工作原理如下:
这种算法的优点在于它在线性时间内运行,只需要恒定的内存开销;事实上,它只是重塑了底层树,而不是创建一个新树并复制旧数据。编码也相对简单。
希望这有帮助!
答案 1 :(得分:15)
“尽可能平衡”= complete (or full) binary tree 1 。你无法更加平衡它。
解决方案很简单 - 构建一个“空”完整二叉树,并在inorder-traversal中迭代新树和输入树(同时)以填充整个树。
完成后,您可以获得最平衡的树,此方法的时间复杂度为O(n)
。
修改强>
这应该按照以下步骤完成:
n
个节点构建虚拟完整树。每个的所有值
节点将被初始化为一些垃圾值。originalIter
用于原始树,(2)newIter
用于新(用垃圾初始化)树。两个迭代器都将按顺序遍历返回元素。执行以下操作以使用原始值填充树:
while (originalIter.hasNext()):
newIter.next().value = originalIter.next().value
(1)(来自维基百科):一个完整的二叉树是一个二叉树,其中除了可能是最后一个级别之外,每个级别都被完全填充,并且所有节点都尽可能地离开
答案 2 :(得分:10)
DSW算法可以解决这个O(n)时间问题。算法如下:
1] Using right-rotation operations, turn the tree into a linked list
(a.k.a. backbone or vine)
2] Rotate every second node of the backbone about its parent to turn
the backbone into a perfectly balanced BST.
答案 3 :(得分:1)
这会将您的常规BST转换为平衡的BST,且其最小高度可能为O(n)。首先,将所有节点保存到向量中。然后,根是mid元素,并递归地在0到mid-1的左边建立一棵树,并在mid + 1到vector.size()-1的树作为右边的孩子。完成所有这些步骤后,root会保持平衡的BST与最小高度。
import java.util.Vector;
public class ConvertBSTIntoBalanced {
public static void main(String[] args) {
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
node1.right = node2;
node2.right = node3;
node3.right = node4;
ConvertBSTIntoBalanced convertBSTIntoBalanced = new ConvertBSTIntoBalanced();
TreeNode balancedBSTRoot = convertBSTIntoBalanced.balanceBST(node1);
}
private void saveNodes(TreeNode node, Vector<TreeNode> nodes) {
if (node == null)
return;
saveNodes(node.left, nodes);
nodes.add(node);
saveNodes(node.right, nodes);
}
private TreeNode buildTree(Vector<TreeNode> nodes, int start, int end) {
if (start > end)
return null;
int mid = (start + end) / 2;
TreeNode midNode = nodes.get(mid);
midNode.left = buildTree(nodes, start, mid - 1);
midNode.right = buildTree(nodes, mid + 1, end);
return midNode;
}
public TreeNode balanceBST(TreeNode root) {
Vector<TreeNode> nodes = new Vector<>();
saveNodes(root, nodes);
return buildTree(nodes, 0, nodes.size() - 1);
}
public class TreeNode {
public Integer val;
public TreeNode left;
public TreeNode right;
public TreeNode(Integer x) {
val = x;
}
}
}
我希望它会有所帮助。