在Onlogn中找到数组中的所有差异,其中n是元素的最大范围

问题描述

问题:给定一个排序数组A,可以找到元素与A的所有可能差异,其中每个元素都是[1,...,n]范围内的整数。另外,您可以假设没有重复项。因此,数组的最大大小为

注意:由于上述限制,总的可能差异将在[1,...,n-1]范围内。

示例(对于N = 12):

输入:1、6、10、12
输出:2、4、5、6、9、11

该问题与this one相似,只是n为否。问题中元素的数量,而不是元素的上限。

在同一问题中也有一个答案,这个答案是:https://stackoverflow.com/a/8455336/2109808 这个家伙声称可以使用fft和自卷积实际上在O(nlogn)中完成,但我不明白,而且在在线卷积计算器上尝试时(如this one)似乎也不正确。

那么,有人知道如何在O(nlogn)中实现这一目标吗?

预先感谢您:)

解决方法

OP链接的

This answer建议采取以下步骤:

  1. 假定一个数组中包含非重复元素,其范围为[0, n -1]。*
  2. 创建一个长度为 n 的数组,其中索引与输入元素匹配的元素设置为1,其他元素设置为0。可以在O( n )。例如,在输入数组[1,4,5]中给定,我们创建了一个数组[0,1,1]
  3. 计算自相关函数。可以通过采用FFT,对幅度进行平方,然后采用IFFT来计算。这是O( n log n )。
  4. 对于与输入中存在的差异相对应的索引,输出为非零。索引为0的元素始终为非零,应忽略。查找和打印这些元素是O( n )。

请注意,此过程是不正确的,因为通过FFT计算的自相关函数是循环的。也就是说,给定一个具有两个值0和 n -1的输入数组,输出将在索引1以及索引 n -处具有一个非零元素。 1。为避免这种情况,有必要在步骤#2中将数组的长度设为2 n ,将其中一半设置为0。然后应忽略输出数组的后一半。将数组大小加倍不会改变算法的计算复杂度,仍然是O( n log n )。

*为了简单起见,我更改了OP给定的范围,通过向所有索引添加偏移量来更改此范围很简单。