侧边栏壁纸
博主头像
CoderKui

坐中静,舍中得,事上练

  • 累计撰写 51 篇文章
  • 累计创建 69 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

整数二分 & 实数二分

CoderKui
2021-11-03 / 0 评论 / 0 点赞 / 285 阅读 / 584 字 / 正在检测是否收录...

整数二分

整数二分的本质是寻找边界

  1. 寻找左部分的右边界

    mid = (l + r + 1) / 2

    If(check(mid)):true-> [mid, r] -> l = mid

    ​ false-> [l, mid - 1] -> r= mid - 1

  2. 寻找右部分的左边界

    Mid = (l + r) / 2

    if(check(mid)):true-> [l, mid] -> r = mid

    ​ false-> [mid + 1, r] l = mid + 1

栗子

给定一个按照升序排列的长度为 nn 的整数数组,以及 qq 个查询。

对于每个查询,返回一个元素 kk 的起始位置和终止位置(位置从 00 开始计数)。

如果数组中不存在该元素,则返回 -1 -1

输入格式

第一行包含整数 nn 和 qq,表示数组长度和询问个数。

第二行包含 nn 个整数(均在 1∼100001∼10000 范围内),表示完整数组。

接下来 qq 行,每行包含一个整数 kk,表示一个询问元素。

输出格式

共 qq 行,每行包含两个整数,表示所求元素的起始位置和终止位置。

如果数组中不存在该元素,则返回 -1 -1

数据范围

1≤n≤1000001≤n≤100000
1≤q≤100001≤q≤10000
1≤k≤100001≤k≤10000

输入样例:

6 3
1 2 2 3 3 4
3
4
5

输出样例:

3 4
5 5
-1 -1
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] nums = new int[n];
        for(int i = 0; i < n; ++i) {
            nums[i] = sc.nextInt();
        }
        while(m-- > 0) {
            int x = sc.nextInt();
            int l = 0, r = n - 1;
            while(l < r) {
                int mid = l + r >> 1;
                if(nums[mid] >= x) r = mid;
                else l = mid + 1;
            }
            if(nums[l] != x) {
                System.out.println("-1 -1");
            } else {
                System.out.print(l + " ");
                l = 0;
                r = n - 1;
                while(l < r) {
                    int mid = l + r + 1 >> 1;
                    if(nums[mid] <= x) l = mid;
                    else r = mid - 1;
                }
                System.out.println(l);
            }
        }
    }
    
}

实数二分

实数二分由于不用考虑边界问题,所以很简单。

举个栗子:求x的平方根,例如4的平方根为2

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double x = sc.nextDouble();
        double l = 0, r = x;
        while(r - l > 1e-6) {
            double mid = (l + r) / 2;
            if(mid * mid >= x) {
                r = mid;
            } else {
                l = mid;
            }
        }
        System.out.println(l);
    }
}
0

评论区