【问题标题】:Binary search in 2 sorted integer arrays2个排序整数数组中的二进制搜索
【发布时间】:2015-12-06 20:48:44
【问题描述】:

有一个大数组,由 2 个小整数数组组成,一个在另一个末尾写成。两个小数组都按升序排序。我们必须尽可能快地在大数组中找到一个元素。我的想法是通过 binsearch 在大数组中找到左数组的结尾,然后在小数组上实现 2 binsearches。问题是我不知道如何找到那个结局。如果您有一个想法,如何在不查找较小数组的边界的情况下查找元素,欢迎您!

数组信息:两个小数组都有整数元素,都按升序排序,长度都可以从0到任意正整数,但只能有一份一个元素。 下面是一些大数组的例子:

  1. 1 2 3 4 5 6 7(第二个数组的所有元素都大于第一个数组的最大值)

  2. 100 1(两个数组只有一个元素)

  3. 1 3 5 2 4 62 4 6 1 3 5(最常见的情况)

【问题讨论】:

  • 你的问题是?另外,如果您知道某些事情并且无法证明,那么根据定义,您是否不假设您是正确的?只是说可能想在你的“问题”中多加一点思考和问号。
  • O(n) 将是线性搜索,即您可以查看“大数组”中的每个元素。如果您查看每个元素,那么您必须找到您正在寻找的元素,如果它存在的话。二分查找的作用在哪里?
  • 我想我可以给你一个答案,但我需要关于这两个数组的更多信息[称它们为 A 和 B]。 Q1:他们有重叠的价值观吗? A中的所有值都A:1,2,3 B:7,8,9 还是你可以有A:1,2,3,4,5 B:4,7,9? Q3:A/B的相对长度呢?基本上,尽可能多地添加信息。您是否有可以发布的代表性样本数据,显示所有可能性的多个案例会有所帮助。
  • 好吧,老实说,我没有关于数组的任何其他数据。我也一直在思考这个任务,我明白,如果没有更多信息,可能无法完成任务。因此,在没有更多数据的情况下,这样的数组中的搜索不能少于 O(n) 时间,但不幸的是,我还没有证明这一说法。你同意这个想法吗?
  • 不,我不同意——为了你的利益 :-)。我仍然认为它在不到 O(n) 的时间内是可行的。如果没有“缩小”信息,这仅意味着必须尝试 所有“案例”,直到找到匹配项。我认为只有大约 8 个 [(例如)有更多信息,这可能是 [say] 4]。即使我们只打到最后一个,它仍然比线性好。我正在开发一个概念验证程序,该程序将测试所有可能的场景。不过,这里已经很晚了,所以我得把它推到明天。

标签: algorithm binary-search


【解决方案1】:

这个问题不可能在保证的时间复杂度比 O(n) 更快地解决,并且对于某些数组根本不可能解决。二进制搜索在 O(log n) 中运行排序数组,但不保证大数组是排序的,并且在最坏的情况下需要每个元素进行一次或多次比较,即 O(n)。最佳保证时间复杂度是 O(n),使用简单算法:将每个项目与其邻居进行比较,直到找到 A[i] > A[i+1] 的“转折点”。但是,如果您使用广度优先搜索,您可能会很幸运并早日找到“转折点”。

证明问题对于某些数组是无法解决的:让数组M = [A B] 成为我们的大数组。为了找到数组相遇的点,我们正在寻找一个索引i,其中M[i] > M[i+1]。现在让A=[1 2 3]B=[4 5]。数组M 中没有条件成立的索引,因此问题对于某些数组是无法解决的。

前者的非正式证明:让M=[A B]A=[1..x]B=[(x+1)..y] 是两个排序数组。然后交换元素xyM中的位置。如果不(在最坏的情况下)检查每个索引,我们就无法找到x 的索引,因此问题是 O(n)。

二分搜索依赖于每次比较能够消除一半的解决方案空间,但在这种情况下,我们无法从数组中消除任何东西,因此我们无法比线性搜索做得更好。

(从实际的角度来看,您永远不应该在程序中这样做。两个数组应该是分开的。如果这不可能,请将其中一个数组的长度附加到更大的数组中。)

编辑:在问题更新后更改了我的答案。对于 some 数组,它可能比线性时间更快,但不是所有可能的数组。这是我对使用广度优先搜索的算法的想法:

Start with the interval [0..n-1] where n is the length of the big array.
Make a list of intervals and put the starting interval in it.
For each interval in the list:
    if the interval is only two elements and the first element is greater than the last
        we found the turning point, return it
    else if the interval is two elements or less
        remove it from the list
    else if the first element of the interval is greater than the last
        turning point is in this interval
        clear the list
        split this interval in two equal parts and add them to the list
    else
        split this interval in two equal parts and replace this interval in the list with the two parts

我认为广度优先的方法会增加找到早于A[first] > A[last] 的区间的几率。请注意,如果转折点位于两个区间之间,则此方法将不起作用,但它可以帮助您入门。我会自己测试一下,但不幸的是我现在没有时间。

【讨论】:

  • 在您的第一个示例中,如果找到数组之间的实际边界或者您认为边界位于大数组(因此将问题视为 A 或 B 为空)。
  • @EmilVikström 不清楚这些值将用于什么。例如,假设 A 是班级中所有女孩的长度,B 是所有男孩的长度。对于应用程序来说,保持区别而不是将最高的女孩与男孩放在一起可能很重要。
  • 真的!如果两个数组的值不能直接比较,我们确实需要知道确切的数组边界。我也意识到所问的问题是如何找到该边界,而不是真正如何找到元素。因此,鉴于这些限制,您的示例非常有效,并且可能会在家庭作业中给予加分(如果学生自己意识到而不是询问)。
  • @David 感谢您的回复!很抱歉我没有把问题表述得足够清楚。所以,我需要在数组中找到一个元素,它是由标题中描述的算法制成的。我的意思是找到左侧数组的末尾,然后在两个数组上进行 binsearch。如果数组之间没有边界,那就太棒了,因为我只需要进行 1 次 binsearch。再一次,目标是尽可能快地找到元素,我真的不明白为什么没有算法比 O(n) 花费更少的时间在这样的数组中找到一个元素。
  • Cambronnes,您没有指定这两个数组是否代表相同类型的数据。都是整数吗?例如,我们可以假设第一个数组中的3 与第二个数组中的3 含义相同吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
相关资源
最近更新 更多