考虑一个深度为 h 的完整三叉树,它由一个根连接到三个深度为 h - 1 的完整三叉树上。有 n = 3^h 个叶子,每个叶子都有一个与之关联的布尔值。每个内部节点,包括根,都等于其大多数子节点的值。
这是深度为 2 的树的示例:
给定叶子输入向量 [0, 0, 1, 0, 1, 0, 1, 1, 1],我们想找到树的根。为了找到根,我们可以评估所有的叶子和内部节点(即 3^h 操作)。但是我们也许能够评估更少的节点。在上面的示例中,我们可以看到第一个内部节点(最左边)的值可以在检查其前两个子节点后进行评估。类似地,在 depth = 1 时,前两个节点足以找到树的根。
我一直在思考这个问题,但我找不到解决问题的好方法。
import numpy as np
import random
class node:
def __init__(self):
self.low = None
self.mid = None
self.high = None
def put(self, low, mid, high):
self.low = low
self.mid = mid
self.high = high
return self
class ternary_tree:
def __init__(self, leaves, count= 0):
self.leaves = leaves
self.root = node()
self.value = None
self.count = count
def get_root(self):
self.root.put(self.leaves[0], self.leaves[1], self.leaves[2])
self.value = majority(self.root)
return self.value
def majority(node):
global ops_count
r1, r2, r3 = random.sample([node.low, node.mid, node.high], 3)
if r1 > 0:
ops_count += 1
if r2 > 0:
ops_count += 1
return 1;
elif r3 > 0:
ops_count += 1
return 1;
else:
return 0;
else:
ops_count += 1
if r2 == 0:
ops_count += 1
return 0;
elif r3 == 0:
ops_count += 1
return 0;
else:
return 1;
if __name__ == "__main__":
h = 2 # depth of the tree
my_leaves = [random.randint(0,1) for i in range(0, 3**h)] #input vector
ops_count = 0 #Counting the number of steps
nb_trees = len(my_leaves) // 3
my_trees = [ternary_tree(leaves=my_leaves[i:i+3]) for i in range(0, nb_trees)]
new_leaves = []
t1, t2, t3 = random.sample(my_trees, 3)
new_leaves.append(t1.get_root())
new_leaves.append(t2.get_root())
if new_leaves[0] == new_leaves[1]:
new_leaves.append(new_leaves[0])
else:
new_leaves.append(t3.get_root())
ternary_tree(leaves=new_leaves).get_root()
我认为代码完成了这项工作,但它仍然检查所有内部节点并且不跳过冗余节点,这并不是最佳的。我认为正确的方法是使用像二叉搜索树这样的递归算法,但我无法在 BST 和多数树评估之间建立联系。
如果您能给我任何有关如何解决此问题的指示,我将不胜感激。谢谢!
插图来自这里: http: //www.math.ucsd.edu/~gptesler/188/MajTree/majtree.html。