简记二分算法模板与代码案例:整数二分和浮点数二分

news/2024/10/18 0:31:37/

本文以 Java 语言实现,整理的代码模板适用于编程竞赛。对代码模板原理的讲解不多,主要记录一下如何使用。

目录

一、算法模板

(1)整数二分

(2)浮点数二分

二、例题

例题:acwing-789.数的范围

例题:数的平方根

例题:acwing-790.数的三次方根 


一、算法模板

(1)整数二分

整数二分有两套算法模板,这两套算法模板几乎涵盖了所有二分算法的题目。

它们的主要区别在于①和②处 对 mid 的赋值不同,相应的,右边界 r 与左边界 l 的值的更新也就不同。二分首先要做的是确定边界,整数二分的本质在于边界的判断。每次都必须选择答案所在的区间进行处理。

在运用下面两套模板时,先不要管细节;找到题干中要求的性质的边界后,先套上模板即可;然后再对边界点作出考虑:如果 check() 的值为 true,边界点包括不包括在目标区间内?根据这个问题的结果,填充:

if(check()) {...    //填充
}else{...    //填充
}

再根据实际填充的结果,对应到下面的模板,确定 mid 的赋值处是否要加一。 

// 检查x是否满足某种性质
boolean check(int x) {...
}// 模板一:当区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用
int bsearch_1(int l, int r) {while (l < r) {int mid = (l + r) >> 1;    //①if (check(mid)) {r = mid; // check()判断mid是否满足性质} else {l = mid + 1;}return l;
}// 模板二:当区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用
int bsearch_2(int l, int r) {while (l < r) {int mid = (l + r + 1) >> 1;    //②if (check(mid)) { l = mid;} else { r = mid - 1;}return l;
}

(2)浮点数二分

浮点数二分与整数二分的逻辑是相同的。不过,由于浮点数的除法结果是浮点数,因此不存在边界问题,相对来说更加简单,也不用考虑mid取值加一减一的问题。


二、例题

例题:acwing-789.数的范围

解析:

这道题直接暴力是会超时的,最好的方法就是二分求解。

如果要查找起始点:

由上面的分析过程和代码模板可得如下代码:

// 二分找开始点
int l = 0, r = n-1;
while(l < r) {int mid = (l+r) >> 1;if(array[mid] >= k) {r = mid;}else{l = mid + 1;}
}

因为下面的步骤是 r = mid 和 l = mid + 1,所以, mid 的赋值即为 (l+r) >> 1,不用再更改为  (l+r+1) >> 1 。

然后二分查找终点

因此,得出查找终点的代码如下:

// 二分找结束点
l = 0;
r = n-1;
while(l < r) {int mid = (l+r+1) >> 1;if(array[mid] <= k) {l = mid;}else{r = mid - 1;}
}

题干可能不一定有解,但是二分的模板是一定有解的。二分后,通过性质,我们可以自行判断出无解的情况是什么。本题中,二分代码结束后 l 于 r 一定是相等的。此时,若 k 不等于 array[l],那么说明要查找的数不存在。 

结合题干要求的输入输出格式,补充完整代码:

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner reader = new Scanner(System.in);int n = reader.nextInt();   //数组长度int q = reader.nextInt();   //询问个数int[] array = new int[n];for (int i = 0; i < array.length; i++) {array[i] = reader.nextInt();}while(q != 0) {q--;int k = reader.nextInt();   //要查询的元素// 二分找开始点int l = 0, r = n-1;while(l < r) {int mid = (l+r) >> 1;if(array[mid] >= k) {r = mid;}else{l = mid + 1;}}//没找到if(array[l] != k) {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(array[mid] <= k) {l = mid;}else{r = mid - 1;}}System.out.println(l);}}reader.close();}
}

例题:数的平方根

用浮点数二分的方法,求输入一个数 x 的平方根。结果保留6位小数。 

由此,可以得出代码:

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner reader = new Scanner(System.in);double x = reader.nextDouble();double l = 0, r = x;while(r - l >= 1e-8) {double mid = (l+r)/2;if(mid * mid >= x) {r = mid;}else{l = mid;}}System.out.printf("%.6f", l);reader.close();}
}

注意,若题干要求结果保留6位小数,精度就设为1e-8,若题干要求保留4位小数,精度就设为1e-6

要求保留几位小数,就把精度设置的比要求的大 2 位。

例题:acwing-790.数的三次方根 

首先我们要识别出,这道题可用浮点数的二分来解。

二分首先要确定边界,该题中,可以直接将数的区间范围确定为 -10000~10000。与求平方根同理:

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner reader = new Scanner(System.in);double n = reader.nextDouble();double l = -10000, r = 10000;while(r - l >= 1e-8) {double mid = (l+r)/2;if (mid * mid * mid >= n) {r = mid;} else {l = mid;}}System.out.printf("%.6f", l);reader.close();}
}

数的立方根同题也在蓝桥杯中考过:蓝桥-解立方根 


http://www.ppmy.cn/news/55569.html

相关文章

详解达梦数据库字符串大小写敏感

检查数据库实例大小写敏感信息 场景一、初始化数据库实例为大小写敏感库 DDL操作 总结&#xff1a; 大小写敏感的数据库中&#xff1a; 创建表时&#xff1a; ①如果不对表名或列名添加""&#xff0c;那么表名和列名都自动转换为大写形式&#xff1b; ②如果对表…

带你了解现在的LED显示屏技术

随着LED显示屏技术的空前繁荣&#xff0c;LED显示屏产品备受关注&#xff0c;广泛应用于商业广告、实况播映、交通诱导、舞台演绎等领域&#xff0c;发展至今。你了解十大中国LED显示屏制造商吗&#xff1f; LED显示屏技术已经得到了长足的发展&#xff0c;现在的LED显示屏技术…

什么是DHCP?为什么要用DHCP?(中科三方)

在传统网络环境下&#xff0c;网络管理者需要手动为网络内的每一台主机分配IP地址&#xff0c;将硬件地址与IP进行绑定&#xff0c;但这种手动配置的方式一般仅适用于静态环境&#xff0c;且如果网络内的某台主机废置不用还会造成IP地址的浪费。 而随着网络规模的不断扩大以及…

多种内网穿透的实现方案

1. 内网穿透的应用场景 1.1. 开发调试 比如企业微信、钉钉等开发&#xff0c;需要一个回调地址&#xff0c;开发的时候&#xff0c;希望回调到开发的电脑上&#xff0c;打断点进行调试&#xff0c;这就需要穿透到内网的开发机器。 1.2. 演示测试 有需要演示或测试的系统&am…

openEuler社区人才评定考试流程指引

最近因为公司工作的需要参加考试了openEuler社区人才评定考试&#xff0c;本次考试题型主要包括单选、多选、判断三类题型。考试内容基本都是操作系统使用相关的内容。 考试需要注意事项&#xff1a; 1.考试为线上答题考试&#xff0c;需开启摄像头。 2.考试期间请保持周围环…

Whistle安装与使用

1、安装npm 网上搜索安装教程&#xff0c;但是使用npm安装软件的时候一直报错 修复方案&#xff0c;将http改成https 2、安装whistle : npm install whistle -g 以及配置见下面两篇文章 爬虫工具—whistle安装与使用 - 简书 whistle安装以及使用_奔跑的蜗牛_爱阳光的博客-C…

LeetCode876. 链表的中间结点

876. 链表的中间结点 描述示例解题思路以及代码解法1解法2 描述 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 示例1 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5] 解释…

设计模式--装饰者模式

问题 星巴克可乐订单 (1) 可乐种类/单品可乐 :BaiShiCola(百事可乐) FeiChangCola(非常可乐) CoCola(可口可乐) (2) 调料/附品: Milk Chocolate (3) 要求在扩展新的可乐种类时 要具有良好的扩展性 改动方便 维护方便 (4) 使用OO的来就算不同之类可乐的费用 客户可以点单品…