合并排序是一种排序算法,其工作原理是将给定列表分为两半,对两个较小的列表进行递归排序,然后将它们合并回一个排序的列表。递归的基本情况是到达一个单例列表,该列表无法进一步拆分,但已按定义进行了排序。
[1,7,6,3,3,2,5]
可以通过以下方式可视化列表中算法的执行:
[1,7,6,3,3,2,5]
/ \ split
[1,7,6,3] [3,2,5]
/ \ / \ split
[1,7] [6,3] [3,2] [5]
/ \ / \ / \ | split
[1] [7] [6] [3] [3] [2] [5]
\ / \ / \ / | merge
[1,7] [3,6] [2,3] [5]
\ / \ / merge
[1,3,6,7] [2,3,5]
\ / merge
[1,2,3,3,5,6,7]
任务
编写一个程序或函数,以任何合理的方式将整数列表作为输入,并可视化此列表的不同分区,同时通过合并排序算法对其进行排序。这意味着您不必输出上述图形,而只需列出即可:
[1,7,6,3,3,2,5]
[1,7,6,3][3,2,5]
[1,7][6,3][3,2][5]
[1][7][6][3][3][2][5]
[1,7][3,6][2,3][5]
[1,3,6,7][2,3,5]
[1,2,3,3,5,6,7]
此外,任何合理的列表符号都可以,因此以下内容也是有效的输出:
1 7 6 3 3 2 5
1 7 6 3|3 2 5
1 7|6 3|3 2|5
1|7|6|3|3|2|5
1 7|3 6|2 3|5
1 3 6 7|2 3 5
1 2 3 3 5 6 7
最后,只要两个结果列表的长度最多相差一个,就可以将列表分为两个较小的列表。这意味着除了拆分[3,2,4,3,7]
为[3,2,4]
and之外[3,7]
,您还可以通过采用偶数和奇数索引([3,4,7]
and [2,3]
)的元素进行拆分,甚至每次都随机化拆分。
这是code-golf,因此以字节为单位的任何语言中最短的代码都会获胜。
测试用例
如上所述,实际格式和将列表分为两半的方法取决于您。
[10,2]
[10][2]
[2,10]
[4,17,1,32]
[4,17][1,32]
[4][17][1][32]
[4,17][1,32]
[1,4,17,32]
[6,5,4,3,2,1]
[6,5,4][3,2,1]
[6,5][4][3,2][1]
[6][5][4][3][2][1]
[5,6][4][2,3][1] <- Important: This step cannot be [5,6][3,4][1,2], because 3 and 4 are on different branches in the the tree
[4,5,6][1,2,3]
[1,2,3,4,5,6]
[[1,2],[3],[4,5],[6]]
阶段实际上是正确的解决方案,因为合并排序是递归的。也就是说,如果我们从开始[1,2,3,4,5,6]
并将其拆分为[1,2,3]
和[4,5,6]
,则这些列表将被独立处理,直到在最后一步中将它们合并。
[3]
和[2,1]
,则它们位于不同的分支上,因此我们不能合并[3]
,[2]
之后[2,1]
拆分为[2]
and [1]
。