二叉树中的平衡和

时间:2012-07-21 21:23:54

标签: algorithm tree

我发现了一个有趣的算法问题。我们给出了一个二叉树,它在叶子之外的每个顶点都有0值。在叶子中我们有两个选择:

  1. 值未知,但我们知道这是一个自然数> = 1

  2. 值已知且是自然数> = 1

  3. 问题是决定是否可以在叶子中设置每个未知值,使得给定树的每个子树在其左右子树中的顶点中具有相同的值总和。

    例如:

    树1:

          0
         / \
        0   ?
       / \
      0   5
     / \
    ?   ?
    

    答案是否定的 - 考虑到每个问号必须是自然数,当然不可能

    tree2:

            0
         /     \
        0      0
       / \    / \
      0   10 ?   ?
     / \
    5   ?
    

    答案是肯定的 - 我们在每个问号中分别设置:5,10,10。

    到目前为止,我只提出了一个明显的算法 - 我们创建了线性方程组,并检查它是否有自然数的解。但我认为对于大树来说它可能会非常缓慢,它应该是解决它的更好方法。有人可以帮忙吗?我将非常感激。

2 个答案:

答案 0 :(得分:2)

这是可并行化的。您可以创建从叶子到根的方程组,在每个顶点合并方程(和计算)。当一个方程组变得不可能时,中止所有计算。

这种非并行模拟将是短路评估。

答案 1 :(得分:2)

我认为递归解决方案效果很好。在每个节点获得左右儿童的重量。您有以下情况:

  1. L和R都是已知的:如果f L == R
  2. ,则节点有效
  3. L或R都不知道:此节点未知且具有多重性 是L和R
  4. 的最大多重性的两倍
  5. L或R中的一个是未知的:如果是,则此节点有效 已知孩子的体重可被整数加倍整除 未知的孩子。它的重量是已知儿童体重的两倍。
  6. 这里的想法是你需要跟踪某个节点下面有多少个未知孩子,因为值只能是整数。多重性总是加倍,因为在一个节点上,即使其左边的孩子有4个未知数且右边有1个未知数,那么1个未知数必须是4的倍数,因此该节点的多样性需要为8。 / p>

    注意:我在这里使用的是multiplicity这个词并不是很正确,但我想不出一个好词。

    以下是Go中的代码,它在您的示例中演示了此解决方案:

    package main
    
    import (
      "fmt"
    )
    
    // Assume that (Left == nil) == (Right == nil)
    type Tree struct {
      Val         int
      Left, Right *Tree
    }
    
    func (t *Tree) GetWeight() (weight int, valid bool) {
      if t.Left == nil {
        return t.Val, true
      }
      l, lv := t.Left.GetWeight()
      r, rv := t.Right.GetWeight()
      if !lv || !rv {
        return 0, false
      }
      if l < 0 && r < 0 {
        if l < r {
          return 2 * l, true
        }
        return 2 * r, true
      }
      if l < 0 {
        return 2 * r, r%(-l) == 0
      }
      if r < 0 {
        return 2 * l, l%(-r) == 0
      }
      return r + l, r == l
    }
    
    func main() {
      t := Tree{0,
        &Tree{0,
          &Tree{0,
            &Tree{Val: 5},
            &Tree{Val: -1},
          },
          &Tree{Val: 10},
        },
        &Tree{0,
          &Tree{Val: -1},
          &Tree{Val: -1},
        },
      }
      w, v := t.GetWeight()
      fmt.Printf("%d, %t\n", w, v)
      t = Tree{0,
        &Tree{0,
          &Tree{0,
            &Tree{Val: -1},
            &Tree{Val: -1},
          },
          &Tree{Val: 5},
        },
        &Tree{Val: -1},
      }
      w, v = t.GetWeight()
      fmt.Printf("%d, %t\n", w, v)
    }