二分探索のポイントは、查找范围
探索範囲を外さずに正しく見つけることができれば、考え方の半分は正しく、残りの半分は、不要死循环
この2点が分かれば基本的に問題ないということです左闭右闭
。よく使われるのは次のようなものです。
l = # 左边界
r = # 右边界
# 按照左闭右闭查找
while l <= r:
mid = (l + r) // 2
if f(mid) < condition:
l = mid + 1
elif f(mid) > condition:
r = mid - 1
else:
# 条件满足时触发。。
return mid
r
このテンプレートの利点は、基本的にエラーがなく、汎用的であることですが、難点は、返信の具体的な内容 (通常はメインの内容)を明確にする必要があることです。
· 左右の境界(エンドポイント)を見つける
# 找左边界
l = 0
r = len(nums) - 1
l_ans = -1
while l <= r:
mid = (l + r) // 2
if nums[mid] < target:
l = mid + 1
elif nums[mid] > target:
r = mid - 1
else:
# 找左边界
l_ans = mid
r = mid - 1
if l_ans < 0:
return r + 1
else:
return l_ans
# 找右边界
l = 0
r = len(nums) - 1
l_ans = -1
while l <= r:
mid = (l + r) // 2
if nums[mid] < target:
l = mid + 1
elif nums[mid] > target:
r = mid - 1
else:
# 找右边界
r_ans = mid
l = mid + 1
if l_ans < 0:
return r + 1
else:
return l_ans
左右の境界を見つけるのも難しい点です。リートコード 34 と 35 の質問を参照してください。条件がトリガーされたときの処理に注意するだけで済みます。
他の山からの翡翠:
優れたバイナリ検索の概要: Github
バイナリ検索より 優れたソリューションと概要: Leetcode-liweiwei1419 より