我一直在试图解决这个问题的答案,但是没有成功,也许您可以带领我一点点: 我们更改合并排序,以便在您对数组进行排序时停止并返回该数组,而无需调用另外2个递归调用。 例如,让我们在一个数组上运行该算法,使数组中的每个数字正好出现n / log(n)次,(以便该数组恰好包含log(n)个不同的数字),那么运行时间的复杂度是多少?>
答案 0 :(得分:1)
“我们更改了合并排序,以便在您对数组进行排序时停止并返回该数组,而无需调用另外2个递归调用。”
这就是常规合并排序的工作方式。在对数组(或数组的一部分)进行排序之后,它不再调用任何递归调用,它仅返回排序后的数组。递归称为,以便首先对数组的部分进行排序。
也许您想说“在递归地对两半排序并合并之前,我们先检查数组是否已排序”。对于具有不同编号的数组,这将毫无用处,因为对数组进行排序的可能性极低(1/n!
)。
在您的示例中,它更有趣,但是,如果数组只有log(n)
个不同的数字,我建议对唯一值进行排序并创建一个从值到索引的哈希映射,这仅在log(n)
上是快速的值,然后您可以在线性时间中进行排序,例如使用存储桶排序。
答案 1 :(得分:0)
实际上,您可以通过检查已排序的子数组是否已经按照正确的顺序来尝试并提高合并数组的效率,并跳过合并阶段。通过将左侧子数组的最后一个元素A
与右侧子数组的第一个元素B
进行比较,可以有效地做到这一点。如果为A <= B
,则不需要合并。
此技巧不会增加复杂性,因为它会向每个合并阶段添加一个测试,但不会删除任何递归调用,因为它要求两个子数组都已排序。相反,如果对数组进行排序,确实可以将复杂度降低到线性。
另一种方法是在拆分和递归之前检查数组是否已排序。在一般情况下,这会添加更多的测试,但不会增加复杂性,因为此测试数量也受 N log(N)限制。平均而言,对于未排序的数组,它的成本更高(更多的比较),但对于排序的数组,它的效率更高(测试数量相同,但没有递归)。
您可以尝试在各种测试用例和数组大小上对这两种方法进行基准测试,以衡量影响。