Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在O(n)中查找数组中的所有差异_Java_C_Arrays_Algorithm - Fatal编程技术网

Java 在O(n)中查找数组中的所有差异

Java 在O(n)中查找数组中的所有差异,java,c,arrays,algorithm,Java,C,Arrays,Algorithm,问题:给定一个排序数组a,找出元素与a的所有可能差异 我的解决方案: for (int i=0; i<n-1; ++i) { for (int j=i+1; j<n; ++j) { System.out.println(Math.abs(ai-aj)); } } for(inti=0;i例如,对于元素为{21,22,…,2n}的数组,有n个⋅(n-1)/2可能的差异,并且没有两个是相等的,所以存在O(n2)差异 由于您必须枚举所有数组,因此还需要至少O(n2)个时间

问题:给定一个排序数组a,找出元素与a的所有可能差异

我的解决方案:

for (int i=0; i<n-1; ++i) {
  for (int j=i+1; j<n; ++j) {
    System.out.println(Math.abs(ai-aj));
  }
}

for(inti=0;i例如,对于元素为{21,22,…,2n}的数组,有n个⋅(n-1)/2可能的差异,并且没有两个是相等的,所以存在O(n2)差异


由于您必须枚举所有数组,因此还需要至少O(n2)个时间。

首先考虑的是,您没有使用数组已排序的事实。让我们假设它是按递增顺序排列的(递减可以类似地处理)

我们还可以使用差异望远镜(i>j):

现在构建一个新的序列,称为s,它有简单的区别,意思是
(a_i-a_(i-1))
。这只需要一次(
O(n)
)就可以完成,你也可以跳过重复,意思是跳过
a_i
如果
a_i=a_(i+1)


i>j
的所有可能的差异
i-a\j
的形式是
s\u i+s\u(i+1)+…+s\u(j+1)
。因此,如果你把它算作已经找到了它们,那么你就在
O(n)
时间内完成了。然而,打印它们可能需要多达
n(n-1)/2次调用,这肯定是
O(n^2)

排序与否无关紧要,如果必须计算每个差异,则无法在小于n^2的时间内计算


这个问题被问错了,或者你只是做了O(n),然后打印了42个其他的n次:D

你可以得到另一个反例,假设数组内容在排序之前是随机整数。那么Ai-Aj与Ak-Al,甚至Ai-Aj与Aj-Ak这两个差异相同的几率太小,不可能只有O(n)明显的差异Ai-Aj

有鉴于此,面试官的问题是解释允许O(n)解的特殊情况。一种可能性是数组值都是0..n范围内的数字,因为在这种情况下,最大绝对差只有n


我可以用O(n lgn)来做,但不能用O(n)。用大小为n+1的数组表示数组内容,其中元素i设置为1,其中数组中有一个值i。然后使用FFT将数组与自身进行卷积-在卷积的第k个元素为非零的情况下,存在一个差值Ai-Aj=k。

如果采访者喜欢理论游戏,可能他正在考虑使用表格输入和结果的e?任何对输入大小有限制且有已知解决方案的问题都可以通过查表来解决。假设您首先创建并存储了该表,该表可能很大

因此,如果数组大小受到限制,则问题可以通过查表来解决,而查表(假设某些情况下)甚至可以在固定时间内完成。诚然,即使最大数组大小为两个(假设32位整数),该表也无法放入普通计算机的内存或磁盘中。如果数组的最大大小较大,则您将陷入困境“不适合已知宇宙”的大小。但是,理论上,这是可以做到的


(但事实上,我认为延斯·古斯特德的评论更有可能。)

是的,你肯定能做到这一点,这是一个有点棘手的方法。 要查找O(n)中的差异,需要使用位集(C++)或相应语言中的任何类似数据结构

初始化两个位集,比如A和B 您可以执行以下操作: 对于通过数组的每次迭代: 1—在位集中存储连续差分 2--左移位B 3—将连续差分存储在位集中B 4--取A=A或B

例如,我已经给出了代码- 这里N是数组的大小

for (int i=1;i<N;i++){
    int diff = arr[i]-arr[i-1];
    A[diff]=1;
    B<<=diff;
    B[diff]=1;
    A=A | B;
}

for(int i=1;i首先需要对数组进行排序

让我们考虑一个排序数组ar={1,2,3,4}

那么我们在O(n^2)上做了什么

如果我们把它们都写下来

sum = ( -1-1-1) + (2+ -2-2) + (3+3 -3) + (4+4+4 ) 
我们可以看到

索引0处的数字被添加到总和中0次,并从总和中减去3次。
索引1处的数字与总和相加1次,从总和中减去2次。
索引2处的数字与总和相加2次,从总和中减去1次。
索引3处的数字与总和相加3次,从总和中减去0次

所以我们可以说

the number at index i will be added to the sum for i time 
and will be substracted from the sum for (n-i)-1 time
然后给出了 每个元素都将是

sum = sum + (i*a[i]) – ((n-i)-1)*a[i];

这就是我在链接中给出的答案,但采访者坚持认为有一个O(n)解决方案。因为
a[last]-a[first]
是最大的可能差异,它也是(比)差分值的最大可能数量。所以这在某些方面是线性的,而不是原始数组的大小。也许有一种方法可以检查每个差分是否在时间上与潜在差的数量成线性关系,但我想不出来。是的,O(n^2)是最坏的情况,但请注意,某些差异可能会多次出现。出现了一个问题:是否存在时间复杂度为O(k)或类似的输出敏感算法,其中k是唯一差异的数量?这意味着,例如,对于k=O(n)的特殊输入,算法只需要O(n)。例如,对于形式为[i,i,…,i]的输入,其中i!=0,存在n-1的差异。我会对在这家公司工作感到谨慎…他们可能希望你在P时间内解决NP完全问题…;-)我的猜测可能是你或面试官忽略或无意中听到了一个附加条件。将n定义为差异的数量(输出的大小而不是输入的大小)。嘿,普雷斯托-现在是O(n)。对于排序数组,如果前一个元素等于当前的==重复元素,则查找重复元素很简单。可能问题问得不正确?@bestsss此问题与查找重复元素无关。好的。我知道这是如何使用数组排序的事实的,因为您不必担心绝对值。我仍然不认为这是真的O(n),但这可能是他所拥有的
sum = ( -1-1-1) + (2+ -2-2) + (3+3 -3) + (4+4+4 ) 
the number at index i will be added to the sum for i time 
and will be substracted from the sum for (n-i)-1 time
sum = sum + (i*a[i]) – ((n-i)-1)*a[i];