我正在使用二进制搜索解决问题,当我看到人们在某些地方使用while start < end
时感到困惑,但是在算法中,我的理解是应该使用while start <= end
。
例如,这是Leetcode问题的一种解决方法查找大于目标的最小字母:
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 <= r
?
我真的很困惑。
答案 0 :(得分:0)
这些是实现细节。有多种实现所有内容的方法。
在这种情况下,循环条件是l < r
(不是l <= r
),因为当l == r(即搜索空间中只有一个元素)时,我们不必处理此外,预期结果(ceil)是位置l
上的元素。
并且更新语句为r = mid
(而不是r = mid - 1
),因为该更新是在target < 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: 我假设您最近开始进行具有竞争力的编码,所以对您来说只是一个建议。再次,不要尝试记住实现并专注于算法的关键,因为再次实现同一算法有多种方式。