二分查找(算法实质+模板)

算法实质:

假设目标值在闭区间  [l, r]  中,每次将区间长度缩小一半,当 l = r 时,我们就找到了目标值。

(题目可能无解,二分一定有解)

二分模板(两个)(不会出错、死循环...)

  • 当我们将区间 [l, r] 划分成 [l, mid] 和 [mid+1, r] 时,其更新操作是 r = mid 或l = mid+1,此时 mid 应该取  (l+r) / 2
search_1(l, r){
    while(l<r){
        mid = l+r>>1;
        if(check(mid)) r = mid;  // check()判断mid是否满足性质
        else l = mid+1;
    }
}
  •  当我们将区间  [l, r] 划分成 [l, mid-1] 和 [mid, r] 时,其更新操作是 l = mid 或r = mid-1,此时 mid 应该取 (l+r+1) / 2
search_2(l, r){
    while(l<r){
        mid = l+r+1>>1;
        if(check(mid)) l = mid;
        else r = mid-1;
    }
}

 

ex:

给定一个按照升序排列的长度为 n 的整数数组,以及 1 个查询,返回该查询元素 k 的起始位置和终止位置(位置从 0 开始计数)。如果数组中不存在该元素,则返回 -1 -1

 

import java.io.*;

class Main{
    static int N = 100010;
    static int n;
    static int[] a = new int[N];
    public static void main(String[] args) throws IOException{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(in.readLine());
        String[] str = in.readLine().split(" ");
  
        int l=0, r = n-1;
        # 寻找起始位置
        while(l<r){
            int x = l+r>>1;
            if(a[x]>=k)     
                r = x;
            else
                l = x+1;
        }
        # 如果查询到最后的位置不等于该元素的值,输出-1,-1,否则else
        if(a[l]!=k)
            System.out.println("-1 -1");
        else{
            System.out.print(l+" ");
            # 查询终止位置
            l = 0;
            r = n-1;
            while(l<r){
                int x = l+r+1>>1;
                if(a[x]<=k)
                    l = x;
                else
                    r = x-1;
            }
            System.out.println(l);
        }
    }
}

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值