未排序的移位阵列的位移

时间:2016-10-30 01:38:23

标签: arrays algorithm sorting complexity-theory

我们有一个带有不同条目的未排序数组a_1,a_2,... a_n,我们也知道一个移位数组a_(nk),... a_n,a_1,a_2,...目标是找到给定这两个数组的位移k。当然,存在最坏情况的线性算法O(n)。但我们能比这更好吗?

有一个提示,答案与k分布有关。如果k在0和n之间均匀分布,那么我们必须在O(n)内完成。如果k在其他方面分布,可能会有更好的方法。

4 个答案:

答案 0 :(得分:1)

如果数组中没有重复项(不同的条目),我会用while循环执行此操作,并从0开始递增索引值k,并从开头一次比较两个项目,从一个开始比较一个结束。例如,array1[k] === array2[0]array1[n-k] === array[0]和索引值k应该是上述比较返回true后的位移。

答案 1 :(得分:1)

根据@ greybeard的提示,有一个O(sqrt(n))解决方案。

从第一个列表中,哈希第一个sqrt(n)元素。对于第二个列表,请查看每次按sqrt(n)元素前进的元素。

但是,如果k很小且n很大,我们可能会问是否有一个可能接近O(k)(或更小!)的解决方案。事实上,我声称有一个O(sqrt(k))解决方案。

为此,我建议增加步长的增量过程。所以算法看起来像这样:

首先,从第一个列表中获取2个元素 - 对这些值进行散列(并将值的位置保持为查找值,因此应将其视为HashMap,其中键是列表的元素,值是位置)。 将这些元素与第二个列表中的第一个和第三个元素进行比较。 也可以从第二个列表中哈希值。 接下来,查看第一个列表中的第三个元素 - 散列值。在此过程中,查看它是否与第二个列表中找到的任何元素匹配。接下来,在第二个列表中前进3个元素,并比较它的值 - 记住这些值。

继续这样: 从第一个列表增加前缀长度,并在每个点增加第二个列表的步长。每当你为第一个列表获取一个新元素时,你必须将它与第二个列表中的值进行比较,但这很好,因为它不会显着影响性能。

请注意,当前缀长度为p时,您已经检查了第二个列表中的第一个p *(p + 1)/ 2个元素。因此,对于给定的k值,此过程将要求前缀长度p约为sqrt(2k),根据需要为O(sqrt(k))。

答案 2 :(得分:1)

基本上,如果我们知道a[0]不等于b[0],我们就不需要检查a[1]是否等于b[1]。扩展这个想法并散列a's,检查可以如下:

a[0] == b[0] or b[0] in hash?   => known k's: 0
a[1] == b[2] or b[2] in hash?   => known k's: 0,1,2
a[2] == b[5] or b[5] in hash?   => known k's: 0,1,2,3,4,5
a[3] == b[9] or b[9] in hash?   => known k's: 0,1,2,3,4,5,6,7,8,9
a[4] == b[14] or b[14] in hash? => known k's: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
...

(我认为这是O(sqrt n)时间和空间最坏情况的复杂性。)

答案 3 :(得分:0)

也许如果将它们合并到哈希表中。那么原始数组中(n-k)的访问和比较时间将为O(1)。