【问题标题】:What is the best search method for O(log(m)) time complexity?O(log(m)) 时间复杂度的最佳搜索方法是什么?
【发布时间】:2020-08-09 03:26:47
【问题描述】:

我正在寻找最佳搜索算法,它返回排序数组中元素的索引 O(log(m)),其中 m 是 k 之前的元素数。
注意: 如果 k 不在数组中,m 是最接近 k 的元素之前的元素数。

我想到了一个搜索,每一步都呈指数增长,不一定从中间开始。

【问题讨论】:

    标签: arrays algorithm sorting search time-complexity


    【解决方案1】:

    您正在寻找Exponential search

    在指数搜索中,我们将索引从 0 以 2 的幂次方跳跃,直到到达一个值高于我们正在寻找的数字的索引。即让我们说数字在索引 14 我们跳转到索引 16 并停止,因为第 16 个索引中的数字大于我们的数字。时间复杂度为O(log m),因为我们在通过 m 的那一刻停止了 2 的幂。

    然后我们在 0 和我们在上一步中停止的索引之间执行二进制搜索。为什么?由于现在上下界之间的数字不超过 2m,所以二分查找的时间复杂度为O(log (2m)),即O(log m),我们就完成了!

    伪代码:

    exponential_search:
     Array A 
     Key k
    
    1. i = 1
    2. while A[i - 1] < k and i <= size of A
    2.1.  i = i * 2
    
    // Now i is no more than 2 * m
    
    3. perform binary search with k and A between 0 and i
    4. return the binary search's result
    

    【讨论】:

      【解决方案2】:

      首先,让我们尝试使k 的范围尽可能小。我们将查看元素a[0], a[1], a[2], ... a[2 ** i], ...,直到找到大于k 的元素。假设我们停在索引r。那么我们肯定知道,因为数组是有序的,如果k在数组中,那么它的位置m小于r。另一个对时间复杂度至关重要的事实是m &gt; i/2。这是真的,因为在上一步我们查看了a[r/2],它小于k

      如果我们对子数组a[0 ... r] 进行简单的二分搜索,我们将在O(log r) 中找到k。查找r 的总步骤数为O(log r)。由于r &gt; m &gt; r/2log r &gt; log m &gt; log r - 1 是真的。因此我们可以将O(log r)重写为O(log m),这正是我们所需要的。

      这是我在 Python 3 中的解决方案:

      def find(a, k):
          if a[0] > k:
              return -1
      
          r = 1
          while r < len(a):
              if a[r] > k:
                  break
              r *= 2
      
          if r >= len(a):
              if a[-1] < k:
                  return -1
              r = len(a) - 1
      
          l = -1
          while r - l > 1:
              m = (l + r) // 2
              if a[m] < k:
                  l = m
              else:
                  r = m
      
          if a[r] == k:
              return r   
          else:
              return -1
      

      【讨论】:

      • 我还想指出,如果您在算法完成之前找到k,您应该始终停止。
      猜你喜欢
      • 1970-01-01
      • 2018-11-26
      • 1970-01-01
      • 2020-03-21
      • 1970-01-01
      • 2022-10-24
      • 2011-07-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多