序列 A = [a1,a2,...,an] 是一个谷序列,如果有一个索引 i < / b> 1&lt;我&lt; n 这样:
a1 > a2 > .... > ai
和
ai < ai+1 < .... < an.
给出一个谷序列必须包含至少三个元素。
我真正感到困惑的是,我们如何在 O(log n)中找到找到元素 ai 的算法,如上所述/ b> 时间? 它是否类似于 O(log n) 二进制搜索?
如果我们有一个二进制搜索算法,在 O(log n) 时间内找到一个数组的元素,我们可以将运行时改进为 O(log log n) ?
答案 0 :(得分:2)
要使用BIG-O( logn )算法,我们必须在恒定时间内将问题大小减少一半。
具体来说,在这个问题中,我们可以选择一个中点,并检查它的斜率是增加,减少还是减少。
Java代码示例:
输入:[99,97,89,1,2,4,6],输出:1
public int findBottomValley(int[] valleySequence) {
int start = 0, end = valleySequence.length - 1, mid;
while (start + 1 < end) {
mid = start + (end - start) / 2;
if (checkSlope(mid, valleySequence) < 0) {
// case decreasing
start = mid;
} else if (checkSlope(mid, valleySequence) > 0) {
// case increasing
end = mid;
} else {
// find our target
return valleySequence[mid];
}
}
// left over with two points
if (valleySequence[start] < valleySequence[end]) {
return valleySequence[start];
}
return valleySequence[end];
}
辅助函数checkSlope(index, list)
将检查列表索引处的斜率,它将检查三个点,包括索引-1,索引和索引+ 1.如果斜率减小,则返回负数;如果斜率增加,则返回正数;如果index - 1和index + 1处的数字都大于index处的数字,则返回0;
注意:该算法假设:
由于数组的随机访问已经是常数O(1),因此具有O( logn )访问时间可能对算法没有帮助。
答案 1 :(得分:1)
有一种解决方案可以像二进制搜索一样工作。设置a = 2并且b = n-1。在每个步骤,我们将仅需要考虑具有索引k的候选者使得a <= k <= b。计算m =(a + b)/ 2(整数除法,因此向下舍入),然后考虑索引m - 1,m和m + 1处的数组元素。如果这些元素正在减少,则设置a = m并继续搜索。如果这些元素增加,则设置b = m并继续搜索。如果这些元素形成一个谷序列,则返回m作为答案。如果b - a&lt; 2,然后没有山谷。
由于我们每次都将搜索空间减半,因此复杂性是对数的。是的,我们访问三个元素并在每个阶段执行两次比较,但计算将显示仅影响常数因子。
请注意,这个答案取决于这些序列严格减少然后增加。如果连续元素可以重复,最好的解决方案在最坏的情况下是线性的。
刚看到第二部分。一般来说,没有,一种在对数时间内找到特定元素的方法 - 甚至是恒定时间 - 一般来说都是无用的。问题是我们真的没有任何有用的想法。如果所有元素的值的间距大于它们在数组中的间距 - 这不难排列 - 那么我就看不出你如何选择要搜索的内容。