【发布时间】:2023-04-03 09:59:01
【问题描述】:
首先,这个问题的双调数组被定义为这样一个数组,对于长度为 N 的数组中的某个索引 K,其中 0
示例:[1、3、4、6、9、14、11、7、2、-4、-9]。它从 1 单调增加到 14,然后从 14 减少到 -9。
我担心的是我无法理解在双音序列中寻找最大元素的二分搜索。
【问题讨论】:
首先,这个问题的双调数组被定义为这样一个数组,对于长度为 N 的数组中的某个索引 K,其中 0
示例:[1、3、4、6、9、14、11、7、2、-4、-9]。它从 1 单调增加到 14,然后从 14 减少到 -9。
我担心的是我无法理解在双音序列中寻找最大元素的二分搜索。
【问题讨论】:
您基本上是在搜索位置 m,这样项目会增加到 m,然后从它开始减少。
修改regular binary search 可以解决这个问题。
您的搜索在 l 和 r 之间的每次迭代中进行,分别初始化为 0 和 n - 1。
在每次迭代中,选择 m = ⌊(l + r) / 2⌋。检查 m 的左右邻居(除了 m = 0 或 m = n - 1,您只检查一个邻居),并比较这三个元素。分三种情况:
左边的邻居更小,右边的邻居更小 - m 处的元素就是你想要的。
左边的邻居小,右边的邻居大 - 你需要向右搜索。
左边的邻居较大,右边的邻居较小——需要向左搜索。
当您向左或向右移动时,您可以像通常的二分搜索一样调整 l 和 r。
除以下内容外,终止也与常规二进制搜索一样。请注意,如果它终止于您没有找到右下邻居的点,则答案在 n - 1;如果它以找到左下邻居而终止,则答案为 0。
【讨论】:
返回给定双调数组中最大元素的索引(先升序,后降序,无重复):
private int findMax(int[] array, int low, int high) {
int mid = low + (high-low)/2;
if (high == low) return high; // max has be found
else if (array[mid] < array[mid+1]) {
return findMax(array, ++mid, high); // search in the right subarray
} else {
return findMax(array, low, mid); // search in the left subarray
}
}
【讨论】: