假设我有一个已排序的数组[1, 2, 3, 4, 5, 6]
。我可以应用二进制搜索来查找任何数字,但我的二进制搜索逻辑中需要做什么修改如果我的排序数组向左移动了一些未知数字。与[4, 5, 6, 1, 2, 3]
一样。
答案 0 :(得分:7)
我们可以使用二分搜索找到班次。我们需要找到第一个小于给定数组的第一个元素的数字。像这样:
def getShift():
if a[n - 1] > a[0]:
return 0 // there is no shift
low = 0 // definitely not less than a[0]
high = n - 1 // definitely less than a[0]
while high - low > 1:
mid = (low + high) / 2
if a[mid] < a[0]:
high = mid
else
low = mid
return high
现在知道转变,以便我们可以在两个时间间隔内执行标准二进制搜索:[0, shift)
和[shift, n - 1]
。
时间复杂度为O(log n)
(因为我们运行了3次二进制搜索)。
答案 1 :(得分:1)
在未知班次后重新排序数组。它的计算成本很高,但它是正确的。
此外,您还可以在此处进行线性排序,因为排序和搜索将采用O(n * log(n))。通过强力进行线性搜索只能是O(n)。
答案 2 :(得分:1)
您只需要执行一次常规二进制搜索算法,并在逻辑上修改何时选择上部或下部搜索窗口。修改基于与移位数组中第一个元素的额外比较,以便您知道所在阵列的哪个部分。您可以在不必实际找到拆分的精确位置的情况下执行此操作。
在红宝石中:
LIST = [6,7,8,9,10,1,2,3,4,5]
def binary_search(x)
first = LIST[0]
low = 0
high = LIST.size-1
while low <= high
mid = low + (high-low)/2 # avoid overflow
return mid if x == LIST[mid]
if (LIST[mid] < first) != (x < first) || LIST[mid] < x
low = mid + 1
else
high = mid - 1
end
end
return -1 # not found
end
1.upto(10) do |x|
puts "#{x} found at index #{binary_search(x)}"
end
输出:
1 found at index 5
2 found at index 6
3 found at index 7
4 found at index 8
5 found at index 9
6 found at index 0
7 found at index 1
8 found at index 2
9 found at index 3
10 found at index 4
答案 3 :(得分:0)
实际上有一个未知的转变,你仍然可以做二进制,但它有点不稳定。
一种方法是将列表的大小加倍,即:
[4,5,6, 1,2,3, 4,5,6, 1,2,3]
# basically mylist.extend(mylist)
正如你所看到的,我只是将尺寸加倍,但中间部分仍然是有序的。
现在您可以浏览列表
list[i-1] > list[i]
这将是您开始二进制搜索,最后相同的金额将是您的二进制列表的结尾。
start = i
end = len(list) -1
现在你可以进行二进制搜索
根据数据平均值可能会低于O(n)
您可以使用列表并执行二进制搜索:
O(nlog(n)) + log(n)
所有元素的线性搜索
O(n)
答案 4 :(得分:0)
简单的二进制搜索,无需加倍或排序或任何其他数组预处理
所以让我们开始
l = 0;
r = n-1;
和
m = (l + r)/2
如果我们正在搜索价值v:
1) 如果 (l和m之间没有跳跃)
array[l] < v < array[m] or
(如果在l和m之间有跳跃)
v < array[m] < array[l] or
array[m] < array[l] < v
比l在l和r之间,我们可以制作 r = m
2)如果v等于array [l] array [r]或array [m],我们发现它
3)在所有其他情况下,v介于m和r之间,我们可以使l = m
4)重复新的l和r