我一直在尝试解决以下问题。我有一个积极的序列 可能非常长的整数(几百万个元素)。这个 序列可以在元素值中包含“跳转”。前面提到的跳跃 表示两个连续的元素相差超过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。
我的想法是以某种方式修改二进制搜索算法,但是由于存在环绕,我不确定是否可能。值得一说的是,最多只能发生两个跳转,并且在这些跳转之间对元素进行排序。有人知道吗?预先感谢您的任何建议。
答案 0 :(得分:0)
您无法找到有效的解决方案(有效意味着不查看所有数字,O(n)),因为您无法通过查看少于所有的数字得出任何有关数字的结论。例如,如果仅查看第二个数字(仍然是O(n),但系数更好),则可能会错过两次跳跃:1 5 3
。您可以并且必须查看每个数字,并将其与邻居进行比较。您可以分担工作量并使用多核方法,仅此而已。
更新
如果您的特殊情况是列表中只有1个跳转,其余的已排序(例如1 2 3 7 8 9
),则可以非常有效地找到此跳转。您不能使用普通的二进制搜索,因为列表可能未完全排序,并且您不知道要搜索的数字,但是可以使用指数搜索的缩写,该缩写有点相似。
我们需要以下假设才能使该算法起作用:
基于这些假设,我们现在基本上正在寻找单调性的中断。这意味着我们正在搜索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