【问题标题】:What is the O time in determining if a value is in a sorted array?确定一个值是否在排序数组中的 O 时间是多少?
【发布时间】:2009-01-22 20:04:58
【问题描述】:

我有一个 5000 个整数的排序数组。我能以多快的速度判断一个随机整数是否是数组的成员?一般来说,C 和 Ruby 的答案会很好。

数组值的格式为

c * c + 1

其中c 可以是 1 到 5000 之间的任何整数。

例如:

[2, 5, 10, 17, 26, 37, 50 ...]

【问题讨论】:

  • 我不是在寻找减一并取 sqrt() 并测试它是否是一个 int。 ;)
  • 好吧,您也可以查看stackoverflow.com/questions/295579/… 了解其他不涉及查看数组的方法。
  • 固定大小总是 O(1) ;)
  • @A. Rex:我会推荐相同的方法,但我仍然认为 sqrt 会比使用二分搜索时的最多 13 次比较要慢。我可能是错的。
  • 这个数组中的所有值都是 1-5000 还是其中有多次?

标签: arrays complexity-theory big-o binary-search


【解决方案1】:

log(n) 用于 c 上的二进制搜索

【讨论】:

    【解决方案2】:

    我会说它是 O(const)! :)

    给定一个随机数 r,检查它是否是一个可以用 (n*n+1) 形式表示的数字是很简单的。只需检查 sqrt(r-1) 是否为整数!

    (好吧,它可能比这更复杂一些,因为您的编程语言可能会在处理整数与浮点数时引入一些复杂性,但仍然:您根本不需要搜索数组:只需检查是否数字就是这种特殊的形式。)

    【讨论】:

    • 如果这确实有效,而且看起来应该有效,那么当其他所有人(包括我)都将其视为搜索问题时,您就是一个解决这个问题的天才。我希望我可以多次投票...
    【解决方案3】:

    正如其他人所提到的,二分搜索是 O(log2N),并且可以递归编码:

       BinarySearch(A[0..N-1], value, low, high) {
           if (high < low)
               return -1 // not found
           mid = (low + high) / 2
           if (A[mid] > value)
               return BinarySearch(A, value, low, mid-1)
           else if (A[mid] < value)
               return BinarySearch(A, value, mid+1, high)
           else
               return mid // found
       }
    

    或迭代:

       BinarySearch(A[0..N-1], value) {
           low = 0
           high = N - 1
           while (low <= high) {
               mid = (low + high) / 2
               if (A[mid] > value)
                   high = mid - 1
               else if (A[mid] < value)
                   low = mid + 1
               else
                   return mid // found
           }
           return -1 // not found
       }
    

    但是,如果您正在寻找最快的方法,您可以根据您的号码的sqrt(N-1) 设置查找表。只需 5,000 字的内存,您就可以通过这种方式实现 O(1) 查找。

    解释:

    由于对于从 1 到 N 的整数 N,所有数字的形式为 N^2 + 1,因此您可以创建一个包含 N 个元素的表。位置 i 处的元素将指定 i^2 + 1 是否在您的数组中。该表可以用一个长度为 N 的简单数组来实现。构建需要 O(N) 和 N 个单词的空间。但是一旦你有了表,所有的查找都是 O(1)。

    例子:

    这是 Python 中的示例代码,读起来像伪代码,一如既往:-)

    import math
    
    N = 5000
    ar = [17, 26, 37, 50, 10001, 40001]
    
    lookup_table = [0] * N
    
    for val in ar:
        idx = int(math.sqrt(val - 1))
        lookup_table[idx] = 1
    
    def val_exists(val):
        return lookup_table[int(math.sqrt(val - 1))] == 1
    
    print val_exists(37)
    print val_exists(65)
    print val_exists(40001)
    print val_exists(90001)
    

    建表最多占用O(N),查找O(1)。

    【讨论】:

      【解决方案4】:

      从技术上讲,在固定大小的数组中查找元素的复杂性是恒定的,因为 log2 5000 不会改变。

      【讨论】:

        【解决方案5】:

        二分查找是 O(log n)

        WikiPedia

        【讨论】:

          【解决方案6】:

          如果数组有 n 个元素,则 O(log n)

          【讨论】:

            【解决方案7】:

            只是为了扩展它:它是 lg n 测试,即 log2 n。这使得它 O(log n)。为什么?因为二进制搜索的每次尝试都会将数组分成两半;因此需要 lg n 次试验。

            【讨论】:

              【解决方案8】:

              使用二分搜索,它是 Log(N) 搜索时间。

              bool ContainsBinarySearch(int[] array, int value) {
                return Array.BinarySearch(arrray, value) >= 0;
              }
              

              【讨论】:

                【解决方案9】:

                在 Perl 中:

                我会将值加载到静态哈希中,然后它会是 O(1)。

                构建查找哈希

                lookup_hash{$_} = 1 foreach (@original_array);

                查找语法

                ($lookup_hash{$lookup_value}) && print "在 O(1) 中找到它 - 这里没有循环\n";

                【讨论】:

                • 仅仅因为“可见”代码是一个语句长,这不会使实际查找 O(1)。哈希查找不是一个固定时间的操作,它取决于哈希的大小和特定的查找算法(不确定 Perl 内部使用的是哪一种)。
                • DanM - 实际上,Perl 的散列将非常接近 O(1),尤其是对于这个数量的元素(即不是很大)
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2018-01-11
                • 2020-11-16
                • 2011-08-04
                • 2012-03-12
                • 1970-01-01
                • 1970-01-01
                • 2015-12-19
                相关资源
                最近更新 更多