简体   繁体   English

如何设计时间复杂度为O(n log n)的搜索算法?

[英]How to design a search algorithm with time complexity O(n log n)?

Describe a O(n log n)-time algorithm that, given a set S of n integers and another integer x , determines whether or not there exist two elements in S whose sum is exactly x. 描述一个O(n log n)时间算法,给定一组Sn个整数和另一个整数x ,确定在S中是否存在两个元素的总和恰好是x。

Im planning on using binary search for this. 我正在计划使用二进制搜索。

ALGORITHM(S,x)
S=Insertion-Sort()
for i=1 to S.length
   n=x-S[i]
   if( Binary-Search(S,n) == true)
      return { S[i],n }


Binary-Search(A, v)
low=1
high=A.length

while low ≤ high
   mid=(low+high)/2

   if v = A[mid]
     return mid
   if v > A[mid]  
      low ← mid+1
   else
      high ← mid−1
 return NIL 

How do I find the time complexity of this algorithm? 如何找到该算法的时间复杂度? And if T(n) is not (n log n) , what's the correct algorithm? 如果T(n)不是(n log n) ,那么正确的算法是什么?

The overall order of an algorithm is dominated by the highest order of the individual pieces. 算法的总体顺序由各个部分的最高顺序决定。 You're starting out with an insertion sort whose worst-case performance is O(n^2) so you've already failed. 您从最坏情况下的性能为O(n ^ 2)的插入排序开始,因此您已经失败了。

If you were to replace the sorting algorithm with a O(n log n) version then you'd have to look at what's left. 如果要用O(n log n)版本替换排序算法,则必须看看还剩下什么。 You have a single loop of length n with a body that calls a binary search. 您有一个长度为n的单循环, 其中有一个调用二进制搜索的主体。 A properly coded binary search is O(log n) so the result should be O(n log n). 正确编码的二进制搜索为O(log n),因此结果应为O(n log n)。 Adding two O(n log n) processes still leaves you with O(n log n). 将两个O(n log n)进程相加仍然会留下O(n log n)。

There's an alternate faster way to do the second step but I'll leave that for you to discover. 还有另一种更快的方法可以执行第二步,但我将留给您发现。 It wouldn't affect the overall result. 这不会影响整体结果。

As the other answers point out, you can do it using an O(n log n) sort at first and then search for the complement of each element in O(log n) time each element, thus adding up to O(n log n) overall. 正如其他答案所指出的那样,您可以首先使用O(n log n)排序,然后在每个元素O(log n)中搜索每个元素的补数,从而得出O(n log n) ) 总体。

However, I think you can also do the following to have an O(n) algorithm. 但是,我认为您也可以执行以下操作来获得O(n)算法。

Observe that if the sum of two numbers is x, one of them has to be >= x/2, and another <= x/2. 请注意,如果两个数字的总和为x,则其中一个必须>> x / 2,另一个必须为<= x / 2。 So, divide the array into two parts by the pivot x/2, one that is greater and one which is less. 因此,用枢轴x / 2将数组分为两部分,一个更大,另一个更小。 This takes O(n) time. 这需要O(n)时间。 In case there are more than one element with value x/2, you are done. 如果有多个元素的值x / 2,则操作完成。

Now build a hashtable of xi for all elements i in the lower array. 现在为下部数组中的所有元素i生成xi的哈希表。 This takes O(n) time again. 这又需要O(n)时间。

Now search for each element in the high array in the hashtable in constant time per lookup. 现在,在每次查询中以固定的时间搜索哈希表中高位数组中的每个元素。 Thus, this too is O(n). 因此,这也是O(n)。

Hence, overall complexity, O(n). 因此,总体复杂度为O(n)。

For each element i : 对于每个元素i

  • If xi is in the hash table, we have our sum ( i and xi ) 如果xi在哈希表中,我们有和( ixi
  • Insert i into the hash table. i插入哈希表。

Total running time - O(n) . 总运行时间O(n)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM