给出一维数组。该数组的每个数字与前一个数字相差+1或-1。示例:数组{5,6,7,6,5,6,7,8,9,8}
您将获得一个数字来搜索此数组中的第一个匹配项(例如:搜索8 - 您的代码应返回7)。不要使用线性搜索。
如果没有线性搜索,我可以尝试如下:
Check if (array[0] == Key)
{
YES:
return 0;
}
Take a variable: Diff = array[0]
// Keep on traversing the array, if Next Number>Current Number
Diff += 1
Else
Diff -= 1
if (Diff==key)
{
return current_index+1;
}
但这种方法过于通用。即使键之间的差异不是+ -1而是其他东西,这种方法也可以解决这个问题。
有什么特别关于+ -1差异,这可以给我一个更好的解决方案?
感谢。
答案 0 :(得分:8)
假设您正在搜索16,并且数组[0] = 8.这意味着您搜索的数字不会出现在数组[8]之前,即(目标 - 数组[0])。所以你读了数组[8],它有13个;这意味着目标不能出现在数组[11]之前。等等。 +/- 1差异允许您在搜索中向前跳过,因为您知道如果array [x] =(target +/- N)目标数字不能出现在array [x + N]之前。
答案 1 :(得分:5)
您无需查看列表中的每个数字。假设您正在寻找8
,第一个数字是5
。您可以安全地执行步骤3,因为8不能在少于三个步骤中发生。您可能会考虑稍微多一点 - 比如6 - 因为可能有一些-1,但我不知道这是否会更有效,因为您不确定它是否是“第一次”发生。所以我们坚持使用原文:
当你到达新的号码时,你确定下一步要采取的步骤 - 如果你已经采取了3步,你会找到6,再步2(8-6),你又找到6,再走2,你找到8 - 你在那里!你知道这是第一次出现,因为你跳过的数字不能是8.而且它只需要三步而不是七步。
答案 2 :(得分:5)
所选答案不是最佳选择。如果您正在尝试最小化探测次数(数组查找),那么您可以做得比从头开始搜索更好,并采取小到`target - array[i]
的步骤
由于您被允许使用索引查找进行随机访问,因此您可以进行更大的步幅。例如,如果您在以a[0] = 0
开头的数组中查找 9 ,则可以检查a[16]
以查看它是否小于或等于 0 < / em>的。如果没有,那么a[0 .. 16]
都不能达到 9 。
更大的步幅为每个探针提供更多信息(每个探针都允许您排除左侧和右侧的指示)。与从左侧搜索时的最小步幅相比,这使得每个探测器获得的信息量增加了两倍。
为了展示从左边搜索到中间搜索的优势,这里有一些用Python编程语言编写的工作代码:
def find(arr, value, bias=2):
# With the bias at 2, new probes are in the middle of the range.
# Increase the bias to force the search leftwards.
# A very large bias does the same as searching from left side of the range.
todo = [(0, len(arr)-1)] # list of ranges where the value is possible
while todo:
low, high = todo.pop()
if low == high:
if arr[low] == value: return low
else: continue
mid = low + (high - low) // bias
diff = abs(arr[mid] - value)
if mid+diff <= high: todo.append([mid + diff, high])
if mid-diff >= low: todo.append([low, mid - diff])
raise ValueError('Value is not in the array')
从概念上讲,算法正在尝试获取每个探测可能获得的最大信息量。有时,它会变得幸运并且同时排除大范围;有时,这将是不吉利的,只能排除一个微小的子范围。无论运气如何,它的禁区都将是左侧搜索区域的两倍。
简单的测试代码:
arr = [10, 11, 12, 13, 14, 13, 12, 11, 10, 9, 8, 7, 6, 7, 8]
for i in range(min(arr), max(arr)+1):
assert arr.index(i) == find(arr, i)