与交替标志的二进制树

时间:2015-02-23 06:58:03

标签: c++ algorithm tree

给定具有以下属性的二叉树,其所有叶子节点都处于正(+)符号,然后符号交替到达该路径的根。因此,根据路径,节点可以有多个符号。

现在我们需要找出每条路径的总和以及树的总和。 enter image description here

for ex:
there are 5 paths in the given binary tree.

path 1: 10-2+3-4 = 7

path 2: 19-8+2-3+4 = 14

path 3: 12-11+17-3+4 = 19

path 4: 2-9+1-4 = -10

path 5: 21-9+1-4 = 9


overall sum 39

这里的问题是决定每个节点的符号,该节点由它的底层路径中的叶节点控制。

我可以想到一个具有O(n)时间复杂度和O(n)空间的解决方案,其中我可以保存从根到底的矢量遍历的每个路径&然后从叶节点开始确定每个节点的符号,从而计算每条路径的总和。

现在任何人都可以提出任何改进的方法,其中O(1)空间复杂。 任何递归或迭代方法都是首选。

我希望我已经清楚地解释了这个问题。不过,如果出现任何疑问,我会很快添加更多细节。

编辑:存储二叉树&实现像这样&不在数组中

struct node
{
    int data;
    struct node* left;
    struct node* right;
};

struct node* newNode(int data)

{
  struct node* node = (struct node*)
                       malloc(sizeof(struct node));
  node->data = data;
  node->left = NULL;
  node->right = NULL;

  return(node);
}

int main()
{
  struct node *root = newNode(1);
  root->left        = newNode(2);
  root->right       = newNode(3);
  root->left->left  = newNode(4);
  root->left->right = newNode(5); 
}

无论如何都无法保存存储树所需的空间。请不要去制作树。假设您已获得树的根节点,并且已经构建了树。

我说的是运行特定算法来回答问题所需的额外空间。

1 个答案:

答案 0 :(得分:0)

好吧,如果我们可以从底部到顶部遍历树,我们可以很容易地获得具有O(1)额外空间和O(n ^ 2)时间复杂度的解决方案:

for(every leaf in tree){

   Node node = leaf;
   int total = 0;
   int sign = 1;
   while(node != null){
       total += sign*node.value;
       node = node.parent;
       sign *= -1; 
   }
   print total;
}

对于具有O(n)时间复杂度的从上到下的遍历,为了获得O(1)额外空间,需要更复杂的算法

Node node = root;
Node last = null;
int total = 0;
int sign = 1;
boolean back = false;
while(node != null){
     total += sign*node.value;
     if(node is leaf){
        if(sign == 1)
           print total;//Need to check if sign is not positive
        else
           print -total;
        back = true;//If this is leaf, we need to go back
        total -= sign*node.value;
        last = node;
        node = node.parent;
     }else if(back){
        if(last is left child){
           back = false;
           node = node.rightChild;
        }else{//We need to continue to go back if we are going back and this is right child 
           last = node;
           total -= sign*node.value;
           node = node.parent;
        } 
     }else{
        total += sign*node.value;
        node = node.leftChild;
     }
     sign *= -1; 

}

注意

  • 使用堆栈进行递归的自上而下的遍历或迭代遍历很容易造成O(n)空间复杂度,所以要小心!

  • 如果没有每个Node中的父链接,我们就无法解决这个问题,因为在这种情况下,需要一个类似堆栈的数据结构来遍历树。

<强>更新

由于我们可以更改树中节点的值,因此我们可以修改节点的左侧链接以将其用作父节点的链接。

Node node = root;
Node last = null;
int total = 0;
int sign = 1;
boolean back = false;
while(node != null){
     total += sign*node.value;
     if(node is leaf){
        if(sign == 1)
           print total;//Need to check if sign is not positive
        else
           print -total;
        back = true;//If this is leaf, we need to go back
        total -= sign*node.value;
        Node tmp = last;//For leaf node, we can just use variable last
        last = node;
        node = tmp;
     }else if(back){
        if(last is not right child){
           back = false;
           last = node;
           node = node.rightChild;
        }else{//We need to continue to go back if we are going back and this is right child 
           last = node;
           total -= sign*node.value;
           node = node.leftChild;
        } 
     }else{
        total += sign*node.value;
        Node tmp = node.leftChild;
        node.leftChild = last;
        last = node;
        node = tmp;
     }
     sign *= -1; 

}