我发现用漂亮的图片来思考这种事情是最容易的。我们试着建立一些图表怎么样?
第一个例子
1/2/3/4
1/2/3/5
1/2/4/3
1/2/4/5
1/2/5/3
1/2/5/4
...可能看起来像这样,以图表形式:
从上到下的每条路径(例如1->2->4->3
)对应于初始格式中的一行。
如果我们从该图开始,那么(也许)我们可以在该图上运行一个小算法,以您正在寻找的方式简化它。这是我们将尝试的:
- 从图表顶部开始,逐级向下移动。(第一级仅包含蓝色节点
1
。)
- 对于当前级别中的每个节点,计算子节点的数量。如果只有一个孩子,则跳过该节点。(由于蓝色节点
1
只有一个孩子,我们将跳到绿色节点2
。)
- 对于多个孩子中的每一个,构造一个包含该孩子及其孙子的集合。(红色节点
3
有一个集合{3,4,5}
,红色4
有一个集合{3,4,5}
,红色5
有一个集合{3,4,5}
。)
- 如果这些集合中的任何一个相同,则将关联的孩子/孙子替换为包含孩子的单个节点,指向包含集合的孙子。(因为所有三个红色节点都有相同的集合,所以它们都被替换了。)
第二个例子
1/2/3/4
1/2/3/5
1/2/4/3
1/2/4/5
1/2/5/3
...可能看起来像这样,以图表形式:
红色节点3
和4
具有相同的集合(即{3,4,5}
),因此它们被替换。红色节点与红色节点和5
没有相同的集合,所以我们不理会它。3
4
和以前一样,通过简化树的每条路径代表输出的一行。
(我没有介绍如果在有曾孙时替换子/孙会发生什么。可能是您实际上应该从底行开始并向上工作。)