【问题标题】:Given a sorted list of integers of length N, determine if an element x is in the list给定一个长度为 N 的有序整数列表,确定元素 x 是否在列表中
【发布时间】:2021-02-14 20:56:50
【问题描述】:

要解决的问题是:

给定一个长度为 N 的排序整数列表,确定元素 x 是否在列表中,而不执行任何乘法、除法或位移操作。在 O(log N) 时间内完成此操作。

我已经使用修改后的二进制搜索解决了这个问题,但我不确定这是否满足所需的时间复杂度。有没有更好的解决方案?

def get_mid(start, end):
    mid = start + 1
    sum_ = start + end
    prev = mid
    while mid < end and (mid + mid) != sum_ and (mid + mid + 1) != sum_:
        prev = mid
        mid += mid
    if mid > end:
        return prev
    return mid



def bin_search(arr, x):
    start, end = 0, len(arr) - 1

    while start <= end:
        mid = get_mid(start, end)
        if mid == 1:
            return x in arr[:end]
        if x > arr[mid]:
            start = mid + 1
        elif x < arr[mid]:
            end = mid - 1
        else:
            return True

    return False

【问题讨论】:

  • 二分查找是 O(log n),这正是你应该使用的方法。
  • 但我不确定如何在不除以 2 的情况下进行二分搜索。
  • 如果您不确定是否存在问题,您可能还没有遇到 Stack Overflow 问题......您认为实现的哪一部分是不是 O(n log n),为什么?
  • @Prune 我想可能是get_mid()中的while循环,需要满足禁止除法的要求。
  • @Prune 是的,正如 Barma 所说.. 我还搜索了任何想法进行除以 2 而不进行除法,我发现只有减法方法需要 O(num),这不是一个好的选择对于问题..

标签: python algorithm data-structures binary-search sortedlist


【解决方案1】:

我们可以通过逐位构造索引找到x的索引是否存在:

def find_idx_sorted(arr, x):
    powers_of_two = [1]
    while powers_of_two[-1] < len(arr):
        powers_of_two.append(powers_of_two[-1] + powers_of_two[-1])

    idx = 0
    for pot in reversed(powers_of_two):
        if idx + pot < len(arr) and x >= arr[idx + pot]:
           idx += pot
    
    return idx

那么我们需要做的就是:

def contains_sorted(arr, x):
    return arr[find_idx_sorted(arr, x)] == x

【讨论】:

    【解决方案2】:

    使用 log2(N) 调用只添加而不循环查找:

    def find_pos(step, arr, val):
        next = step+step
        if next < len(arr):
           choose = find_pos(next, arr, val)
        else:
           choose = step
        next = choose + step
        if next < len(arr) and arr[next] <= val:
            return next
        if arr[choose] <= val:
            return choose
        return 0
    
    def find_val(arr, val):
        index = find_pos(1, arr, val)
        if arr[index] == val:
            print "found %d at %d" % (val, index)
        else:
            print "%d not found" % (val)
    

    【讨论】:

      【解决方案3】:

      在 O(logN) 时间内完成,必须使用二进制搜索。所以,这里的关键是找到一种方法来进行除以 2,而无需乘法、除法和位移。 这是一个在恒定时间内执行的函数:

      int divideTwo(int x) {
          vector<int> bit = {
              0x1, 0x2, 0x4, 0x8,
              0x10, 0x20, 0x40, 0x80,
              0x100, 0x200, 0x400, 0x800,
              0x1000, 0x2000, 0x4000, 0x8000,
              0x10000, 0x20000, 0x40000, 0x80000,
              0x100000, 0x200000, 0x400000, 0x800000,
              0x1000000, 0x2000000, 0x4000000, 0x8000000,
              0x10000000, 0x20000000, 0x40000000, 0
          };
      
          int v = 0;
          for (int i = 1; i < bit.size() - 1 && x > 0; ++i) {
              if ((x & bit[i]) > 0)
              {
                  v += bit[i - 1];
                  x -= bit[i];
              }
          }
          return v;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多