【算法】二分查找

基本内容

提高在有序的数组中查找满足某一条件的索引

  • 二分查找的基本类型

    ① 有多种情况满足条件,找到满足条件的最右索引,例如找到值为4的最右索引(也可以换为小于5的最后一个元素)

​ ② 有多种情况满足条件,找到满足条件的最左索引,例如找到大于4的第一个元素...

​ ③ 仅存在一种满足条件的情况,①、②代码都适用

[!note]

可以发现,针对①、②两种情况,可以有不同的问法,例如在②情况中,也可以适用于找到4的最后一个元素,只需要在找到的索引上减一即可找到

  • 基本模板

① 情况

def binary_search(self, l, r, target): 
    while l < r:
        mid = (l + r + 1) // 2  
        if 满足条件:
            l = mid # 因为可能是最右情况,所以要保持不变,不能是 mid + 1, 又因为是需要找到最右情况,所以需要通过l往r逼近
        else:
            r = mid - 1
    return l

② 情况

def binary_search(self, l, r, target): 
    target = l
    while l < r:
        mid = (l + r) // 2  
        if 满足条件:
            r = mid #需要找到最左的情况,所以需要通过r往l逼近
        else:
            l = mid + 1 
    return l
  • 入门例子

查找有序数列中值为4的最后一个元素,[1,3,4,4,4,4,6,8,9]

​ 可以用①、②两种代码解决

条件为小于等于4为情况①

def binary_search(self, l, r, target): 
    while l < r:
        mid = (l + r + 1) // 2  
        if array[mid] <= 4:
            l = mid 
        else:
            r = mid - 1
    return l

条件为大于4为情况②,只需在最后输出的时候进行减一操作

def binary_search(self, l, r, target): 
    target = l
    while l < r:
        mid = (l + r) // 2  
        if array[mid] > 4:
            r = mid
        else:
            l = mid + 1 
    return l - 1 # 因为找到的是大于4的第一个元素6,所以还需要减一操作

题目

二分查找往往需要和其他类型的算法结合,所以题目所需涉及的内容不只是二分查找

  1. 3261. 统计满足 K 约束的子字符串数量 II

滑动窗口 前缀和 二分查找

class Solution:
    def __init__(self):
        self.lefts = None
        self.pre = None
    def binary_search(self, l, r):
        target = l
        while l < r:
            mid = (l + r) // 2  
            if self.lefts[mid] > target:
                r = mid
            else:
                l = mid + 1
        return l - 1
    def countKConstraintSubstrings(self, s: str, k: int, queries: List[List[int]]) -> List[int]:
        self.pre = [0] * (1 + len(s))
        self.lefts = [-1] * len(s)
        left = 0
        cnt = [0, 0]
        ans = []
        for right, x in enumerate(s):
            cnt[ord(x) % 2] += 1
            while cnt[0] > k and cnt[1] > k: 
                cnt[ord(s[left]) % 2] -= 1
                left += 1
            
            self.lefts[right] = left
            self.pre[right + 1] = self.pre[right] + (right - left + 1)

        for i,j in queries:
            if i > self.lefts[j] :
                ans.append( (j - i + 2)*( j -i + 1)//2)
            else:
                h = self.binary_search(i, j)
                ans.append(self.pre[j+1] - self.pre[h+1] + (h-i + 2)*(h-i +1)//2)
        return ans

本文作者:九年义务漏网鲨鱼

本文链接:https://www.cnblogs.com/DLShark/p/18547871

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   九年义务漏网鲨鱼  阅读(4)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.

作曲 : Reol

作词 : Reol

fade away...do over again...

fade away...do over again...

歌い始めの一文字目 いつも迷ってる

歌い始めの一文字目 いつも迷ってる

どうせとりとめのないことだけど

伝わらなきゃもっと意味がない

どうしたってこんなに複雑なのに

どうしたってこんなに複雑なのに

噛み砕いてやらなきゃ伝わらない

ほら結局歌詞なんかどうだっていい

僕の音楽なんかこの世になくたっていいんだよ

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.

目の前 広がる現実世界がまた歪んだ

目の前 広がる現実世界がまた歪んだ

何度リセットしても

僕は僕以外の誰かには生まれ変われない

「そんなの知ってるよ」

気になるあの子の噂話も

シニカル標的は次の速報

麻痺しちゃってるこっからエスケープ

麻痺しちゃってるこっからエスケープ

遠く遠くまで行けるよ

安定なんてない 不安定な世界

安定なんてない 不安定な世界

安定なんてない きっと明日には忘れるよ

fade away...do over again...

fade away...do over again...

そうだ世界はどこかがいつも嘘くさい

そうだ世界はどこかがいつも嘘くさい

綺麗事だけじゃ大事な人たちすら守れない

くだらない 僕らみんなどこか狂ってるみたい

本当のことなんか全部神様も知らない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.