【问题标题】:DIfference between sorted and unsorted array time complexity排序和未排序数组时间复杂度之间的差异
【发布时间】:2019-01-03 18:36:36
【问题描述】:

所以,我对编程和计算机科学非常陌生,并且在解决我的代码时一直在尝试理解时间复杂度的概念。但是,在对数组进行排序时,我总是对一些事情感到困惑: 在我的理解中,用排序数组解决问题应该是最好的情况复杂性,而未排序的数组将有最坏的情况。 我总是感到困惑的是,在涉及搜索的问题中,我们如何真正利用正在排序的数组?意思是,这将如何降低我的时间复杂度,因为我认为我必须运行相同次数的循环。

例如,如果我有一个数组并且想要找到两个索引,其值加起来等于一个特定的目标,如果数组是排序的还是未排序的,时间复杂度会有所不同吗?

提前感谢您帮助我。

【问题讨论】:

  • 如果数组已排序,则可以根据问题有时使用binary search 或其他利用此结构的算法。对于您的示例,yes 这会有所不同,因为在这里我们可以使用两个“光标”:一个向前移动,一个向后移动。
  • 也许你对“排序”的想法过于严格了。如果您的问题是找到两个值加起来为 100 的索引,那么“排序”数组可能是 [40, 60, 1, 200, 9, 83, 17]
  • 答案并不总是显而易见的,请参阅传奇:Why is it faster to process a sorted array than an unsorted array? 但要回到您搜索排序数据的问题,您无需查看所有数组元素,只需在少数 ... 使用二进制搜索在n 数字上只有log2(n) 峰值而不是n 所以不,你没有相同数量的迭代......如果你得到半排序数组(连续)数据,即使这样也可以像How approximation search works

标签: python-3.x algorithm sorting


【解决方案1】:

让我们看一下您的示例问题:找出两个数字之和等于给定数字。

假设您有一个未排序的数组:[2, 8, 1, 3, 6, 7, 5, 4],目标是 11。

所以你看第一项,2,你知道你必须在数组中找到数字 9,如果它存在的话。对于未排序的数组,你必须进行线性搜索以确定数组中是否存在 9。

但如果你有一个排序数组[1, 2, 3, 4, 5, 6, 7, 8],你就有优势。当您看到值 2 时,您知道您需要在数组中找到 9。但是因为列表是排序的,所以可以使用binary search。您不必查看列表中的每个项目,只需查看其中的 3 个:

二分查找会先查看第 4 项,然后是第 6 项,然后是第 8 项,最后确定 9 不在数组中。

简而言之,在未排序的数组中搜索需要 O(n) 时间:您可能必须查看每个项目以了解您要查找的内容是否在那里。排序后的数组可让您加快搜索速度。不必检查每个项目,您只需检查最多 log2(n) 个项目。当数字变大时,这会产生巨大的差异。例如,如果您的列表包含一百万个项目,则二进制搜索只需检查其中的 20 个。顺序搜索必须查看所有百万。

【讨论】:

    【解决方案2】:

    排序数组对于“目标总和”问题的优势甚至更好:您根本不需要搜索数组。相反,您从两端的指针开始。如果总和等于目标,则发出该值并将两个指针移入。如果小于目标,则递增较低的指针。否则,递减上指针。这将在 O(n) 时间内找到所有解决方案——在 O(n log n) 进行排序之后。

    对于 cmets 中给出的情况,[40, 60, 1, 200, 9, 83, 17] 的过程如下所示:

    Sort array:
    [1, 9, 17, 40, 60, 83, 200]
    
    Start your pointers at the ends, 1 + 200
    The sum is 201, too large, so decrement the right pointer.
    Now looking at 1 + 83.  This is too small; increment the left pointer.
    Now looking at 9 + 83.  This is too small; increment the left pointer.
    Now looking at 17 + 83.  This is the target; print (17, 83) as a solution
        and move *both* pointers.
    Now looking at 40 + 60.  This is the target; print (40, 60) as a solution
        and move *both* pointers.
    The pointers have now met (and passed), so you're done.
    

    这是一个很好的例子。通常,对数组进行排序为您提供了多种选项,用于在数组中查找内容比依次检查每个元素要快得多。一个简单的二分搜索是 O(log n),并且有多种方法可以针对特定应用程序调整它。在最坏的情况下,二进制(log base 2)搜索会很好地工作。

    但是,对任意列表进行排序会花费 O(n log n) 作为开销;您需要将这种一次性付款计入您的应用程序的需求中。例如,如果您的数组是按键值(例如姓名或 ID 号)排序的某种数据库,并且您必须根据用户请求执行数百万次搜索,那么以某种方式对数据库进行排序几乎肯定会更好在进行任何搜索之前。

    如果您想要全面介绍,请研究“排序和搜索”。一个很好的参考资料是 Donald Knuth 的同名书。这是“计算机编程的艺术”的第 2 卷。

    【讨论】:

      猜你喜欢
      • 2021-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-27
      • 2013-04-01
      • 2013-03-14
      • 2021-02-11
      • 1970-01-01
      相关资源
      最近更新 更多