【问题标题】:Why does binary search work for this unsorted array?为什么二进制搜索适用于这个未排序的数组?
【发布时间】:2018-06-28 16:59:46
【问题描述】:

鉴于这个问题: 峰值元素是大于其邻居的元素。

给定一个输入数组,其中 num[i] ≠ num[i+1],找到一个峰值元素并返回它的索引。

数组可能包含多个峰,在这种情况下,将索引返回到任何一个峰都可以。

示例:数组 = [1, 4, 5, 7, 4, 3, 1]。峰值指数 = 3(即 7)。

以下代码完美运行(不仅适用于这个测试用例):

    public static int getPeakElement(int[] array, int left, int right) {

    if (left == right) {
        return left;
    }

    int mid = (left + right) / 2;

    if (array[mid] > array[mid + 1]) {
        return getPeakElement(array, left, mid);
    }

    return getPeakElement(array, mid + 1, right);
}   

我不明白它是如何工作的 - 我认为二进制搜索仅适用于排序数组/旋转数组。

【问题讨论】:

  • 可能是因为峰值恰好在中间。尝试交换,比如 5 和 7,它不会再起作用了。
  • 你得到正确的结果只是一个巧合。尝试像 1, 4, 5, 4, 1, 3, 7 这样的数组,你会得到索引 2 而不是 6。
  • @Thomas index 2 在这种情况下是正确的,因为5一个的峰值。
  • @luk2302 我明白了,但它不再是二分搜索了(至少不是那种能找到特定元素的排序)。因此,在 OP 方面,这可能更像是对代码的用途的误解。
  • 我认为它起作用只是因为你必须找到一个峰值,而不是最大的峰值。

标签: java arrays recursion binary-search


【解决方案1】:

如果“峰”的定义仅仅是它是一个比周围元素大的元素,那么您可以推断它为什么起作用。

if (array[mid] > array[mid + 1]) {
    return getPeakElement(array, left, mid);
}

return getPeakElement(array, mid + 1, right);

条件是:

  • 如果中间元素大于相邻元素,则可能是峰 - 它肯定大于其右侧的元素。在“左手”的一半内搜索至少有同样大的峰。
  • 否则,相邻元素可能是峰 - 它肯定大于其左侧的元素。在“右手”的一半中搜索至少同样大的峰。

随着递归的进行,你知道:

  • left-1 在数组之外,或者那里的元素小于arr[left] 的元素(否则你不会选择这一半)
  • right+1 在数组之外,或者那里的元素小于arr[right] 的元素(否则你不会选择这一半)。

您继续直到left == right,此时您知道您已达到峰值,因为相邻元素较少(或者您位于数组的一端或另一端)。

【讨论】:

    【解决方案2】:

    如果有多个峰值,则不需要对数组进行排序。排序实际上会删除除一个峰值之外的所有峰值。

    这段代码是如何工作的?想象一下,你在一条不平坦的道路上,需要找到一个山峰——但你是盲人,所以你看不到它,只能凭感觉工作。你从某个点开始,根据你所在点的坡度检查你是否必须向左或向右走(你左右放一只脚,感受你击中的东西)。然后你迈出一大步(你是Miss Fantastic,所以巨大的台阶对你来说不是问题)并再次检查新位置的斜坡。您以逐渐减小的步长重复此操作,直到到达左右下坡的点,因此您已达到顶峰。

    【讨论】:

      猜你喜欢
      • 2020-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 2020-06-06
      • 2020-05-19
      • 1970-01-01
      • 2019-01-25
      相关资源
      最近更新 更多