给出一个数组,任何两个后续元素之间的距离是一(+1或-1)。我们给出了一个数字。我们如何以最小的复杂度检查数字是否在数组中。
答案 0 :(得分:8)
您可以进行二元搜索。
如果我们要查找的元素位于第一个和最后一个元素之间,我们知道该元素出现在数组中,我们可以停止。
如果不是,请检查数组中可能出现的最小和最大可能值,方法是找出第一个和最后一个元素之间的差异,减去元素数量,将其除以2,然后从/减去/添加两者的最小/最大。
更明确地说:
temp = abs(arr[left] - arr[right]) - (left - right)
minPossible = min(arr[left], arr[right]) - 2*temp
maxPossible = max(arr[left], arr[right]) + 2*temp
递归重复,将数组分成两半(或拆分as Daniel suggested)。
为什么上面给出了最小/最大可能:
可以考虑如下:你需要一些元素,这些元素等于从左边和右边的差异,从一个到另一个。除此之外,对于每一步,你需要再次上/下一步。
仍然不幸的是O(n)最坏的情况。
这就是O(n)最坏情况不能被击败的原因:
(类似于David's proof)。
示例输入= [1,0,1,0,1,0,1,0]
假设我们正在寻找2。
显然不存在,但是如果0中的一个被改为2怎么办?我们需要检查每个零。一旦我们跳过一个,那个就可能是2。
因此我们必须检查至少1/2的元素,因此它仍然是O(n / 2)= O(n)。
答案 1 :(得分:5)
您可以使用以下算法保存检查某些(可能是大多数)元素。
如果你的数字是85并且数组的第一个数字是100,你可以跳过(15-1)= 14个数字(当然15是100和85之间的距离)因为它们最接近85是99,98,97,...,86。所以你只需检查第15个数字。如果该数字不是85,请继续重复相同的算法。这使你可以跳过数组,它仍然是O(N)但可能在时钟时间上比单独检查更快。
最糟糕的情况是:我正在寻找85。
在我阅读this answer之前,我认为这是最佳算法。
答案 2 :(得分:1)
此问题预计单元探测器复杂度为Ω(n),因此不会发生次线性算法。考虑可能的输入
210101010...10
012101010...10
010121010...10
...
010101010...12
概率相等。通过Yao的引理,对于固定输入分布,最佳随机算法并不比最佳确定性算法更好。在找到2之前,所有未被排除的输入看起来都相同。因此,每个正确的确定性算法必须以某种顺序探测0个位置,探测到预期的n / 4(或其附近)位置,直到找到2。
答案 3 :(得分:0)
当然,复杂性不能低于O(N)。那说我会经历整个阵列。
无论何时
我会“破解”算法,将“是”作为答案。
默认情况下,答案是“不”! :)
答案 4 :(得分:0)
假设您在数组中查找值v
。如果在给定位置i
,值a[i]
为v-d
,我们要查找的值至少距离d
i
个单元格的距离。因此,您可以跳过其间的单元格,因为最多可以包含值v-d+1
,v-d+2
等等。所以这里有一个草率的递归算法:
template <class ForwardIter, class T>
ForwardIter find_in_singlestep_range(ForwardIter first, ForwardIter last, T val) {
if (first == last) return last;
if (*first == val) return first;
auto max_diff = last-first;
auto diff = make_signed<T>{val} - make_signed<T>{*first};
if (diff < 0) diff = -diff;
if (diff > max_diff) return last;
return find_in_singlestep_range(first+diff, last, val);
}
复杂性: 你将获得最多1/2 * N +1比较,因为假设你从未遇到过该元素,最坏的情况可能是diff是1,2,2,2,2,所以你跳过每一个元素。 (如果diff是2,则下一个diff只能是2或4。)
如果你进行二分法搜索,也许你有更好的复杂性:如果子阵列的中间元素与val
的差异大于子阵列大小的一半,你可以跳过子阵列中的搜索。
答案 5 :(得分:0)
由于元素之间的差异为1(+1或-1),因此min(array)
和max(array)
之间的任何数字都将在数组中。如果您缓存最小值和最大值,则第一次搜索为O(N)
,其他每次搜索都为O(1)
。
如果数组的元素是分数而不是整数,那么有一个额外的先决条件测试,fractionPart(min(array))-fractionPart(number)==0