二进制搜索修改

时间:2019-03-12 10:35:52

标签: c binary-search

我一直在尝试解决以下问题。我有一个积极的序列 可能非常长的整数(几百万个元素)。这个 序列可以在元素值中包含“跳转”。前面提到的跳跃 表示两个连续的元素相差超过1。

示例01

1 2 3 4 5 6 7 0

在上述示例中,跳转发生在7到0之间。

我一直在寻找一些有效的算法(从时间的角度来看) 查找发生此跳跃的位置。这个问题由于 事实上,可能存在两种情况,其中一种情况是跳跃 是我要寻找的跳跃,另一个是我的环绕 不在寻找。

示例02

9 1 2 3 4 6 7 8

这里9和1之间的第一个跳转是环绕。之间的第二跳 我要寻找的是4和6。

我的想法是以某种方式修改二进制搜索算法,但是由于存在环绕,我不确定是否可能。值得一说的是,最多只能发生两个跳转,并且在这些跳转之间对元素进行排序。有人知道吗?预先感谢您的任何建议。

1 个答案:

答案 0 :(得分:0)

您无法找到有效的解决方案(有效意味着不查看所有数字,O(n)),因为您无法通过查看少于所有的数字得出任何有关数字的结论。例如,如果仅查看第二个数字(仍然是O(n),但系数更好),则可能会错过两次跳跃:1 5 3。您可以并且必须查看每个数字,并将其与邻居进行比较。您可以分担工作量并使用多核方法,仅此而已。

更新

如果您的特殊情况是列表中只有1个跳转,其余的已排序(例如1 2 3 7 8 9),则可以非常有效地找到此跳转。您不能使用普通的二进制搜索,因为列表可能未完全排序,并且您不知道要搜索的数字,但是可以使用指数搜索的缩写,该缩写有点相似。

我们需要以下假设才能使该算法起作用:

  • 只有1个跳转(我忽略“环绕跳转”,因为从技术上讲,它不在以下任何元素之间)
  • 该列表以其他方式排序,并且严格单调递增

基于这些假设,我们现在基本上正在寻找单调性的中断。这意味着我们正在搜索2个元素和b之间有n个元素但不满足b = a + n的情况。如果两个元素之间没有跳转,则必须为true。现在,您只需要查找不能以非线性方式满足此要求的元素,因此可以采用指数方法。此伪代码可能是这样的算法:

let numbers be an array of length n fulfilling our assumptions

start = 0
stepsize = 1
while (start < n-1)
    while (start + stepsize > n)
        stepsize -= 1
    stop = start + stepsize
    while (numbers[stop] != numbers[start] + stepsize)
        // the number must be between start and stop
        if(stepsize == 1)
            // congratiulations the jump is at start to start + 1
            return start
        else
            stepsize /= 2
    start += stepsize
    stepsize *= 2

no jump found