这是我最近遇到的一个面试问题。
给定完整或几乎完整的二叉树的根地址,我们必须编写一个函数将树转换为最大堆。
这里没有涉及数组。树已经建成了。
例如,
1
/ \
2 5
/ \ / \
3 4 6 7
可以将任何可能的最大堆作为输出 -
7
/ \
3 6
/ \ / \
2 1 4 5
或
7
/ \
4 6
/ \ / \
2 3 1 5
等...
我写了一个解决方案,但是使用了前后顺序遍历的组合,但我想在O(n ^ 2)中运行。我的代码提供了以下输出。
7
/ \
3 6
/ \ / \
1 2 4 5
我一直在寻找更好的解决方案。有人可以帮忙吗?
编辑:
void preorder(struct node* root)
{
if(root==NULL)return;
max_heapify(root,NULL);
preorder(root->left);
preorder(root->right);
}
void max_heapify(struct node* root,struct node* prev)
{
if(root==NULL)
return ;
max_heapify(root->left,root);
max_heapify(root->right,root);
if(prev!=NULL && root->data > prev->data)
{
swapper(root,prev);
}
}
void swapper(struct node* node1, struct node* node2)
{
int temp= node1->data;
node1->data = node2->data;
node2->data = temp;
}
答案 0 :(得分:5)
我认为这可以通过以下程序在O(NlogN)时间内完成。 http://www.cs.rit.edu/~rpj/courses/bic2/studios/studio1/studio121.html
假设树中有一个元素,其左右子树都是堆。
E
H1 H2
由E,H1和H2组成的树可以通过使元素E向下游到正确位置而在logN时间内堆积。
因此,我们开始自下而上构建堆。转到最左边的子树,并通过简单的比较将其转换为堆。也为它的兄弟姐妹这样做。然后上去并将其转换为堆。
对每个元素都这样做。
编辑:正如评论中所提到的,复杂性实际上是O(N)。
答案 1 :(得分:2)
如果您可以轻松访问父节点或没有数组表示,如果您可以遍历树以将其记录在数组(O(N))中,那么我不知道如何访问父节点的方式,然后它变得简单。
1
/ \
2 5
/ \ / \
3 4 6 7
from the last parent node to the root node(in your case 5,2,1:
for each node make it compare to their children:
if children is larger than parent, swap parent and children:
if swapped: then check the new children's childrens utill no swap
1
/ \
2 7
/ \ / \
3 4 6 5 check [7] 5<-->7
1
/ \
4 7
/ \ / \
3 2 6 5 check [2] 4<-->2
7
/ \
4 1
/ \ / \
3 2 6 5 check [1] 7<-->1
7
/ \
4 6
/ \ / \
3 2 1 5 check [1] 6<-->1
就是这样! 复杂性应为O(N * LogN)。
答案 2 :(得分:0)
我认为只需修改postOrderTraverse即可完成一项工作。这是O(n)
void Heapify_Min(TreeNode* node)
{
if(! = node) return;
Heapify_Min(node->left);
Heapify_Min(node->right);
TreeNode* largest = node;
if(node->left && node->left->val > node->val)
largest = node->left;
if(node->right && node->right->val > node->val)
largest = node->right;
if(largest != node)
{
swap(node, largest)
}
}
void swap(TreeNode* n1, TreeNode* n2)
{
TreeNode* temp = n1->left;
n1->left = n2->left;
n2->left =temp;
temp = n1->right;
n1->right = n2->right;
n2->right = temp;
}
}
答案 3 :(得分:0)
这是解决此问题的有效代码。
package Test;
import static Test.BinaryTreeNode.swap;
public class TestImplementations {
public static void main(String args[]){
BinaryTreeNode root = new BinaryTreeNode(2,
new BinaryTreeNode(7,
new BinaryTreeNode(5,
new BinaryTreeNode(1),new BinaryTreeNode(6)),
new BinaryTreeNode(9,
new BinaryTreeNode(17))),
new BinaryTreeNode(3,
new BinaryTreeNode(11),new BinaryTreeNode(4))
);
System.out.println(root);
CustomHeap h = new CustomHeap();
h.minHeapify(root);
System.out.println(root);
}
}
class BinaryTreeNode {
private Integer value;
private BinaryTreeNode left;
private BinaryTreeNode right;
public BinaryTreeNode(Integer value){
this.value = value;
this.left = null;
this.right = null;
}
public BinaryTreeNode(Integer value, BinaryTreeNode left){
this.value = value;
this.left = left;
this.right = null;
}
public BinaryTreeNode(Integer value, BinaryTreeNode left, BinaryTreeNode right){
this.value = value;
this.left = left;
this.right = right;
}
public Integer getValue() {
return value;
}
public BinaryTreeNode getLeft() {
return left;
}
public BinaryTreeNode getRight() {
return right;
}
public static void swap(BinaryTreeNode r, BinaryTreeNode c){
Integer val = r.getValue();
r.value = c.getValue();
c.value = val;
}
}
class CustomHeap {
public void minHeapify(Test.BinaryTreeNode r){
if( r == null || (r.getLeft() == null && r.getRight() == null)){
return;
}
minHeapify(r.getLeft());
minHeapify(r.getRight());
if(isMin(r,r.getLeft())){
swap(r,r.getLeft());
minHeapify(r.getLeft());
}
if(r.getRight() !=null && isMin(r,r.getRight())){
swap(r,r.getRight());
minHeapify(r.getRight());
}
}
private Boolean isMin(Test.BinaryTreeNode r, Test.BinaryTreeNode c){
return c.getValue() < r.getValue() ? Boolean.TRUE : Boolean.FALSE;
}
}