【问题标题】:Binary search implementation conditional confusion二分查找实现条件混淆
【发布时间】:2019-09-10 13:59:06
【问题描述】:

我正在使用二分搜索解决问题,当我看到在某些地方人们使用 while start < end 时感到困惑,但在算法中我的理解是它应该是 while start <= end

例如,这里是 Leetcode 问题的解决方案Find Smallest Letter Greater Than Target

def nextGreatestLetter (self, letters: List[str], target: str) -> str:
    l, r = 0, len(letters)-1

    # cross the border
    if target >= letters[-1]:
        return letters[0]

    while l < r:
        mid = (l+r)//2
        if letters[mid] <= target:
            l = mid+1
        else:
            r = mid
    return letters[l]

为什么我们没有减少r = mid - 1,为什么没有while l &lt;= r? 我真的很困惑。

【问题讨论】:

  • 欢迎来到 SO!我写了一个答案,但我的电脑在我发布之前崩溃了。 TL;DR 刚刚阅读en.wikipedia.org/wiki/Binary_search_algorithm。第一部分展示了“经典”二分搜索算法,然后对其进行了修改以使其基本达到此处所示的状态,并说明理由。

标签: binary-search


【解决方案1】:

这些是实现细节。有多种实现方式。

在这种情况下,循环条件是 l &lt; r (不是 l &lt;= r ),因为当 l == r (即,搜索空间中只有一个元素)时,我们不必进一步处理并且预期result(ceil) 是位置l的元素。

更新语句是r = mid(不是r = mid - 1),因为更新发生在target &lt; letters[mid] 时,我们不能在中间丢弃元素,基于此条件。例如,假设 (mid - 1) 处的元素可能小于或等于目标,在这种情况下,我们的结果将是 mid 处的元素。

就像我说的,这些只是实现细节,同样的解决方案也可以这样实现:

def nextGreatestLetter (self, letters: List[str], target: str) -> str:
    l, r = 0, len(letters)-1

    # cross the border
    if target >= letters[-1]:
        return letters[0]

    while l <= r:
        mid = (l+r)//2
        if letters[mid] <= target:
            l = mid+1
        else:
            r = mid - 1
    return letters[l]

我们在循环中处理 l == r 用例的这个实现也是正确的,并且通过了 Leetcode 上的所有测试用例。

PS: 我假设你最近开始了竞争性编码,所以只是给你一个建议。不要试图记住实现并专注于算法的症结,因为有多种实现相同算法的方法。

【讨论】:

  • 随着while循环的一些变化我们可以使用l
  • 是的,你可以。但是,您最终可能会在循环中引入一些复杂的处理。始终尽量让您的程序简单易懂。
猜你喜欢
  • 1970-01-01
  • 2018-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-17
  • 1970-01-01
  • 2023-03-05
  • 2014-05-10
相关资源
最近更新 更多