给定两个数组A和Q(Q的for元素),找到A中差异最小的元素

时间:2018-07-18 09:17:09

标签: arrays algorithm

给出2个不同长度的未排序数组A和Q。对于Q中的每个元素,在A中找到差异最小的元素。

int[] findSmallestDifference(int A[], int Q[]){
   int []result = new int[Q.length];
   // insert code to find difference for each Q
   return result;
}

我在一次采访中遇到了这个问题,我提供了一些解决方案,但有人提到这还不是最佳选择。

我提供的解决方案:

  1. 蛮力:foreach A,foreach Q计算差异,O(A * Q)
  2. 对数组A(Q的foreach元素)进行排序,执行二进制搜索以找到最小的 差异,O(AlogA + QlogA)
  3. 对A和Q进行排序,然后在每个数组上有两个指针以查找差异O(AlogA + QlogQ)

我没想到的最佳解决方案是什么?

3 个答案:

答案 0 :(得分:0)

以下方法可能更快,具体取决于数组中的数据。 但是可以说您有以下两个数组。

A = {1,2,5,11,13} and Q = {3,5,12}

创建两个新数组并填充该数组,以使旧数组中的值是新数组中的索引。因此,新数组的大小是旧数组中最大的数字,重复值将被忽略。例如:

它应该如何工作的示例(伪代码):

A'=null
Q'=null

A' and Q' have the size of the largest number in A or Q
for i < length(A) i++ {
   A'[A[i]]=A[i]
   B'[B[i]]=B[i]
} 

A'= {1,2,null,null,5,null,....,null,11,null,13}
Q'= {null,null,3,null,5,null,....,12,null}

for i < length(A') i++ {
    if(A[i] == Q[i]){ 
       print(A[i])
    } else if (A[i] == null) {
       for(j=1 j < length(A') j++) {
          if(Q[i+j] != null || Q[i-j] != null){ //here you have to be carfull nto go to -negative indices
              print[Q[i-j],Q[i+j],A[i]]
              Break;
          }
       }
    }

}

然后比较两个数组的值以查看值的索引是否已填充。如果未填充,则查找下一个已填充的索引。

此方法的速度取决于稀疏分配两个数组的数目。如果您有非常大的数字(并且相距很远),那么这可能不是最佳选择。

该算法的最佳情况是O(A + Q),最坏情况是O(infinite)。

答案 1 :(得分:0)

对于| Q |的情况,我有一个构想。 <| A |基于Quickselect。想法是对A进行部分排序,同时通过搜索A差异最小的元素来连续处理Q中的元素。

因此,对于Q中的第一个元素,您需要执行类似于搜索的快速选择,以找到差异最小的元素。此搜索将花费O(A),但会对Q中的元素进行部分排序。Q中的第二个元素将已经从第一次搜索中获利,并进一步对A进行排序。

我目前不确定如何计算运行时复杂度,但是它可能比O(A log A)更好,因为在处理完Q中的所有元素之后不一定会对A进行完全排序。在最佳情况下,它可以是O(Q log A)

不确定是否有帮助,但是也许有人可以找出缺失的部分。

答案 2 :(得分:0)

面试的重点可能是细节。 A和Q具有不同的长度

因此,如果A将具有16个元素,而Q具有1个元素,则解决方案2可能不是最优的。

最佳解决方案是使用良好的排序算法(例如合并排序)对较小数组进行排序,该算法的最坏情况下的复杂度为O(NlogN),然后扫描更大的数组数组,并通过二进制排序在较小数组中找到最接近的元素。

您的解决方案2看起来是最优的,但是应该改写。

  • 设置S =较小的数组,B =较大的数组。排序数组S,B的foreach元素,执行二进制搜索以找到最小差异O(SlogS + BlogS)