【问题标题】:Given two arrays A and Q, foreach element of of Q, find the element in A with smallest difference给定两个数组 A 和 Q,对于 Q 的每个元素,找到 A 中差值最小的元素
【发布时间】:2018-07-18 09:17:09
【问题描述】:

给定 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 的每个元素进行排序,执行二进制搜索以找到最小的 差,O(AlogA + QlogA)
  3. 对 A 和 Q 进行排序,然后我们在每个数组上都有两个指针来查找差异,O(AlogA + QlogQ)

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

【问题讨论】:

  • 对于第三种方法,时间复杂度为 O( max( A log A, Q log Q))
  • 就时间复杂度而言,没有比您的方法 2 和 3 更优化的解决方案了。

标签: arrays algorithm


【解决方案1】:

采访的要点可能是细节。 A 和 Q 的长度不同

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

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

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

  • 设置 S = 较小的数组,B = 较大的数组。对数组S排序,对B的每个元素进行二分查找,找到最小的差异,O(SlogS + BlogS)

【讨论】:

  • 你是对的,这也是我认为我缺少的解决方案。
【解决方案2】:

以下方法可以更快,它取决于数组中的数据。 但是假设您有以下两个数组。

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)。

【讨论】:

  • 我想你需要对数组进行排序,这意味着它不会比 O(AlogA+QlogQ) 好?
  • 为什么需要对它们进行排序?
  • 对不起,我没有得到你的解决方案。看起来你需要检查一个元素是否存在于另一个数组中,我认为你不能有效地做到这一点
  • 如果数组 A = 1, 100000005B = 3, 600000。即使只有两个元素,您的方法也需要几分钟时间来索引 A
  • 那么这是一种低效的方法,就像我在答案的最后一句中所说的那样。
【解决方案3】:

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

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

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

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

【讨论】:

  • 对于后面的元素,仍然需要 logA 来搜索。它实际上类似于 AlogA,除非 |Q|
  • @vish4071 我不明白你是如何得出这个结论的。是的,对于后面的元素,它将花费 O(log A),但您只是在寻找 Q 元素,因此它可以下降到 O(Q log A)(最佳情况)。正如我所说,我不知道平均情况。
  • 就是这样!!如果 |Q|~|A|,则与 AlogA 相同。如果|Q|
  • @vish4071 我明白了,所以你说如果 Q
猜你喜欢
  • 2011-02-03
  • 1970-01-01
  • 2018-04-24
  • 2017-09-12
  • 2020-04-17
  • 2021-01-31
  • 1970-01-01
  • 2012-01-21
  • 1970-01-01
相关资源
最近更新 更多