I found an interesting algorithmic problem. We are given a binary tree which has value 0 in every vertex apart from leaves. In leaves we have two options:
value is unknown, but we know it is a natural number >=1
value is known and it is a natural number >=1
The problem is to decide if it is possible to set every unknown value in leaves such that every subtree of a given tree has the same sum of values in vertexes in its left and right subtree.
For example:
tree1:
0
/ \
0 ?
/ \
0 5
/ \
? ?
The answer is NO - taking into consideration that every question mark has to be a natural number, it is of course not possible
tree2:
0
/ \
0 0
/ \ / \
0 10 ? ?
/ \
5 ?
The answer is YES - we set: 5, 10, 10 respectively in every question mark.
So far, I came up only with an obvious algorithm - we create system of linear equations and check if it has a solution in natural numbers. But I think it can be very slow for big trees and it should be a better way to solve it. Can anybody help? I would be very grateful.
I think a recursive solution works just fine. At every node get the weight of the left and right children. You have the following cases:
The idea here is that you need to keep track of how many unknown children are below a certain node, since values can only be integers. Multiplicity always doubles because, at one node, even if its left child has 4 unknowns and its right has 1 unknown, then the 1 unknown will have to be a multiple of 4 and so the multiplicity of this node will need to be 8.
Note: I'm using the word multiplicity here and it isn't really quite right, but I couldn't think of a good word to use.
Here is code, in Go, that demonstrates this solution on your examples:
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)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With