我正在尝试寻找一种找到最佳位置的算法,以将 目标 插入已排序的数组中。
目标是要么返回该项目在列表中的位置,要么返回将其保持列表排序的位置。
所以说我有一个清单:
0 1 2 3 4 5 6 --------------------------------- | 1 | 2 | 4 | 9 | 10 | 39 | 100 | ---------------------------------
我的目标项目是14 它应该返回一个索引位置5
14
5
我目前拥有的伪代码:
array = generateSomeArrayOfOrderedNumbers() number findBestIndex(target, start, end) mid = abs(end - start) / 2 if (mid < 2) // Not really sure what to put here return start + 1 // ?? if (target < array[mid]) // The target belongs on the left side of our list // return findBestIndex(target, start, mid - 1) else // The target belongs on the right side of our list // return findBestIndex(target, mid + 1, end)
我不太确定现在要写些什么。我试图对此采取二进制搜索方法,但这是在5次重写左右之后我能想到的最好方法。
您的代码有几个问题:
mid = abs(end - start) / 2
这是 不是 之间的中间start和end,这是他们之间的距离的一半(四舍五入到整数)。后来,您将其用作确实是有效的索引:
start
end
findBestIndex(target, start, mid - 1)
不是。您可能打算在mid = (start + end) // 2这里使用或其他东西。您还会错过一些索引,因为您跳过了中间部分:
mid = (start + end) // 2
return findBestIndex(target, start, mid - 1) ... return findBestIndex(target, mid + 1, end)
现在,您的基本情况也必须有所不同。一个好的候选人是条件
if start == end
因为现在您肯定知道您已经完成搜索。请注意,您还应该考虑所有数组元素都小于的情况target,因此您需要在最后插入它。
target
如果您从未尝试过二进制搜索,那么很难正确地进行二进制搜索。如果执行二进制搜索,通常会使用以下模式:
lo, hi = 0, n // [lo, hi] is the search range, but hi will never be inspected. while lo < hi: mid = (lo + hi) // 2 if check(mid): hi = mid else: lo = mid + 1
在该条件check是一个单调二元谓词(它始终是false直到某个点和true从该点),该循环后,lo == hi将在范围内的第一个数字[0..n]与check(lo) == true。check(n)隐式地假定它是正确的(这是此方法的魔力的一部分)。
check
false
true
lo == hi
[0..n]
check(lo) == true
check(n)
那么,true对于包括我们目标false位置前后的所有索引以及之前目标位置的所有索引而言,单调谓词是什么?
如果我们考虑一下,我们想在数组中找到比目标大的第一个数字,因此我们只需要插入它就可以了:
lo, hi = 0, n while lo < hi: mid = (lo + hi) // 2 if (a[mid] > target): hi = mid else: lo = mid + 1 return lo;