Algorithm 寻找可能的替代品清单
假设我们有一个二叉树,如下所示: 我正在寻找一种算法来找到A的所有等价性。我得到了一个数组,其中包含树中的元素。规则是,如果一个节点的所有子节点都存在于一个数组中,则相当于该节点存在于该数组中。 例如,如果我们在数组中有B和C,它相当于有一个A。所以在上面的数组中,F+G=C,C+B=A,所以[B,F,G]也相当于A。同样地[defg]也相当于A 我可以递归调用类似checkSubstitute(node)的东西: 这种逻辑有意义吗?另外,我如何使用上述算法存储所有等效数组Algorithm 寻找可能的替代品清单,algorithm,search,recursion,tree,Algorithm,Search,Recursion,Tree,假设我们有一个二叉树,如下所示: 我正在寻找一种算法来找到A的所有等价性。我得到了一个数组,其中包含树中的元素。规则是,如果一个节点的所有子节点都存在于一个数组中,则相当于该节点存在于该数组中。 例如,如果我们在数组中有B和C,它相当于有一个A。所以在上面的数组中,F+G=C,C+B=A,所以[B,F,G]也相当于A。同样地[defg]也相当于A 我可以递归调用类似checkSubstitute(node)的东西: 这种逻辑有意义吗?另外,我如何使用上述算法存储所有等效数组 提前谢谢 您给出的方
提前谢谢 您给出的方法无法正常工作,因为您总是在for循环的第一次迭代中返回一个值。 假设您有一个数组[D]。然后checkSubstitute(B)返回True,而它应该返回False 与其使用for循环,只需对两个子项进行两次显式调用就更容易了。这假定每个节点都有零个子节点或两个子节点。如果一个节点可以有一个子节点,则需要进行一些额外的空检查
#returns true if Node n exists in NodeList seq, or if its equivalent exists in seq.
function exists(n, seq):
if n in seq:
return True
if not n.hasChildren:
return False
return exists(n.leftChild, seq) and exists(n.rightChild, seq)
获得所有等价数组只需要一点组合运算
#gets all possible equivalents for the given node. This includes itself.
#An equivalent is a list of nodes, so this method returns a list of lists of nodes.
function getPossibleEquivalents(node):
ret = new List()
baseCase = new List()
baseCase.append(node)
ret.append(baseCase)
if not node.hasChildren:
return ret
for each leftEquivalent in getPossibleEquivalents(node.leftChild):
for each rightEquivalent in getPossibleEquivalents(node.rightChild):
ret.append(leftEquivalent + rightEquivalent)
return ret
编辑:
通过为循环嵌套N,可以扩展具有0或N个子树的GetPossibleEquivalent:
for each child0Equivalent in getPossibleEquivalents(node.child[0]):
for each child1Equivalent in getPossibleEquivalents(node.child[1]):
for each child2Equivalent in getPossibleEquivalents(node.child[2]):
for each child3Equivalent in getPossibleEquivalents(node.child[3]):
for each child4Equivalent in getPossibleEquivalents(node.child[4]):
ret.append(child0Equivalent + child1Equivalent + child2Equivalent + child3Equivalent + child4Equivalent + child5Equivalent)
如果您想编写一个可以处理具有任意数量子级的树的函数,则需要对每个子级的每个可能等效项进行排序。有些语言已经为您实现了笛卡尔积。例如,在python中:
from itertools import product
def getPossibleEquivalents(node):
ret = [node]
if len(node.children) == 0: return ret
for equivalentTuple in product(map(getPossibleEquivalents, node.children)):
possibleEquivalent = reduce(lambda x,y: x+y, equivalentTuple)
ret.append(possibleEquivalent)
return ret
您给出的方法不能正常工作,因为您总是在for循环的第一次迭代期间返回一个值。 假设您有一个数组[D]。然后checkSubstitute(B)返回True,而它应该返回False 与其使用for循环,只需对两个子项进行两次显式调用就更容易了。这假定每个节点都有零个子节点或两个子节点。如果一个节点可以有一个子节点,则需要进行一些额外的空检查
#returns true if Node n exists in NodeList seq, or if its equivalent exists in seq.
function exists(n, seq):
if n in seq:
return True
if not n.hasChildren:
return False
return exists(n.leftChild, seq) and exists(n.rightChild, seq)
获得所有等价数组只需要一点组合运算
#gets all possible equivalents for the given node. This includes itself.
#An equivalent is a list of nodes, so this method returns a list of lists of nodes.
function getPossibleEquivalents(node):
ret = new List()
baseCase = new List()
baseCase.append(node)
ret.append(baseCase)
if not node.hasChildren:
return ret
for each leftEquivalent in getPossibleEquivalents(node.leftChild):
for each rightEquivalent in getPossibleEquivalents(node.rightChild):
ret.append(leftEquivalent + rightEquivalent)
return ret
编辑:
通过为循环嵌套N,可以扩展具有0或N个子树的GetPossibleEquivalent:
for each child0Equivalent in getPossibleEquivalents(node.child[0]):
for each child1Equivalent in getPossibleEquivalents(node.child[1]):
for each child2Equivalent in getPossibleEquivalents(node.child[2]):
for each child3Equivalent in getPossibleEquivalents(node.child[3]):
for each child4Equivalent in getPossibleEquivalents(node.child[4]):
ret.append(child0Equivalent + child1Equivalent + child2Equivalent + child3Equivalent + child4Equivalent + child5Equivalent)
如果您想编写一个可以处理具有任意数量子级的树的函数,则需要对每个子级的每个可能等效项进行排序。有些语言已经为您实现了笛卡尔积。例如,在python中:
from itertools import product
def getPossibleEquivalents(node):
ret = [node]
if len(node.children) == 0: return ret
for equivalentTuple in product(map(getPossibleEquivalents, node.children)):
possibleEquivalent = reduce(lambda x,y: x+y, equivalentTuple)
ret.append(possibleEquivalent)
return ret
这个逻辑可以很好地生成所有等价的表示,但需要一些重复,如果您愿意,可以检查并更正这些重复。(我将遵循一些python约定,在何处复制内容) 假设您需要[B,C]中所有可能的表示 对于此数组中的每个节点,可以将其替换为其子节点,也可以将其保持原样。递归的基本思想是:
find_equivalent(representation, node){
// representation is a list which is a valid equivalent representation.
child = list_of_children_of_node;
Temp = representation[:]
for each c in child: Temp.insert(child)
find_equivalent(representation, next(node,representation))
N = next(node,Temp)
Temp.delete(node)
Li.append(Temp)
find_equivalent(Temp, N)
// Here next function takes a list and a node and returns the next element from the list after node.
上面的Li是一个表示的全局数组,您需要为添加的每个表示调用find_equired函数。此逻辑可以很好地生成所有等效表示,但需要一些重复,如果需要,您可以检查并更正。(我将遵循一些python约定,在何处复制内容) 假设您需要[B,C]中所有可能的表示 对于此数组中的每个节点,可以将其替换为其子节点,也可以将其保持原样。递归的基本思想是:
find_equivalent(representation, node){
// representation is a list which is a valid equivalent representation.
child = list_of_children_of_node;
Temp = representation[:]
for each c in child: Temp.insert(child)
find_equivalent(representation, next(node,representation))
N = next(node,Temp)
Temp.delete(node)
Li.append(Temp)
find_equivalent(Temp, N)
// Here next function takes a list and a node and returns the next element from the list after node.
上面的Li是表示的全局数组,您需要在添加表示时为每个表示调用函数find_equired。关于查找所有等效数组的代码,如果我们现在扩展树,每个节点现在可以有多个子节点,该怎么办?简单但脆弱的答案是,对循环使用更多。更难但更可靠的答案是,用笛卡尔积替换那些for循环。嗨,凯文,非常感谢你的解释!不过,我不太理解最后一段代码,在递归中使用了“笛卡尔乘积”。它是如何工作的?还有什么方法可以用Java实现它吗?非常感谢。笛卡尔积可以被认为是在一行中模拟多个嵌套的
for
循环的一种方法。将其与倒数第二个代码段进行比较,您可以想象equivalentTuple
等于[child0Equivalent,child1Equivalent,…,child5Equivalent]
。for
循环中的reduce
方法是一种将这些子等价物组合成单个等价物的方法,然后我们可以将其附加到要返回的值集合中。至于在Java中实现笛卡尔积,在StackOverflow的其他部分已经讨论过,因此,我相信这是可能的:关于查找所有等效数组的代码,如果我们现在扩展树,并且每个节点现在可以有多个子节点,该怎么办?简单但脆弱的答案是,对循环使用更多。更难但更可靠的答案是,用笛卡尔积替换那些for循环。嗨,凯文,非常感谢你的解释!不过,我不太理解最后一段代码,在递归中使用了“笛卡尔乘积”。它是如何工作的?还有什么方法可以用Java实现它吗?非常感谢。笛卡尔积可以被认为是在一行中模拟多个嵌套的for
循环的一种方法。将其与倒数第二个代码段进行比较,您可以想象equivalentTuple
等于[child0Equivalent,child1Equivalent,…,child5Equivalent]
。for
循环中的reduce
方法是一种将这些子等价物组合成单个等价物的方法,我们可以将这些子等价物附加到要返回的值集合中。至于在Java中实现笛卡尔积,在StackOverflow的其他地方已经讨论过,因此我确信这是可能的: