面试官:聊一下二分法
来源:cnblogs.com/luoxn28/p/5767571.html
1、二分查找
二分查找是一个基础的算法,也是面试中常考的一个知识点。二分查找就是将查找的键和子数组的中间键作比较,如果被查找的键小于中间键,就在左子数组继续查找;如果大于中间键,就在右子数组中查找,否则中间键就是要找的元素。
/*** 二分查找,找到该值在数组中的下标,否则为-1*/
static int binarySerach(int[] array, int key) {int left = 0;int right = array.length - 1;// 这里必须是 <=while (left <= right) {int mid = (left + right) / 2;if (array[mid] == key) {return mid;}else if (array[mid] < key) {left = mid + 1;}else {right = mid - 1;}}return -1;
}
每次移动left
和right
指针的时候,需要在mid的基础上+1
或者-1
, 防止出现死循环, 程序也就能够正确的运行。
注意:代码中的判断条件必须是
while (left <= right)
,否则的话判断条件不完整,比如:array[3] = {1, 3, 5};
待查找的键为5,此时在(low < high
)条件下就会找不到,因为low和high相等时,指向元素5,但是此时条件不成立,没有进入while()
中。
2、二分查找的变种
关于二分查找,如果条件稍微变换一下,比如:数组之中的数据可能可以重复,要求返回匹配的数据的最小(或最大)的下标;更近一步, 需要找出数组中第一个大于key
的元素(也就是最小的大于key
的元素的)下标,等等。这些,虽然只有一点点的变化,实现的时候确实要更加的细心。
二分查找的变种和二分查找原理一样,主要就是变换判断条件(也就是边界条件),如果想直接看如何记忆这些变种的窍门,请直接翻到本文最后。下面来看几种二分查找变种的代码:
2.1、查找第一个与key相等的元素
查找第一个相等的元素,也就是说等于查找key
值的元素有好多个,返回这些元素最左边的元素下标。
// 查找第一个相等的元素
static int findFirstEqual(int[] array, int key) {int left = 0;int right = array.length - 1;// 这里必须是 <=while (left <= right) {int mid = (left + right) / 2;if (array[mid] >= key) {right = mid - 1;}else {left = mid + 1;}}if (left < array.length && array[left] == key) {return left;}return -1;
}
2.2、查找最后一个与key相等的元素
查找最后一个相等的元素,也就是说等于查找key
值的元素有好多个,返回这些元素最右边的元素下标。
// 查找最后一个相等的元素
static int findLastEqual(int[] array, int key) {int left = 0;int right = array.length - 1;// 这里必须是 <=while (left <= right) {int mid = (left + right) / 2;if (array[mid] <= key) {left = mid + 1;}else {right = mid - 1;}}if (right >= 0 && array[right] == key) {return right;}return -1;
}
2.3、查找最后一个等于或者小于key的元素
查找最后一个等于或者小于key
的元素,也就是说等于查找key
值的元素有好多个,返回这些元素最右边的元素下标;如果没有等于key
值的元素,则返回小于key
的最右边元素下标。
// 查找最后一个等于或者小于key的元素
static int findLastEqualSmaller(int[] array, int key) {int left = 0;int right = array.length - 1;// 这里必须是 <=while (left <= right) {int mid = (left + right) / 2;if (array[mid] > key) {right = mid - 1;}else {left = mid + 1;}}return right;
}
2.4、查找最后一个小于key的元素
查找最后一个小于key
的元素,也就是说返回小于key
的最右边元素下标。
// 查找最后一个小于key的元素
static int findLastSmaller(int[] array, int key) {int left = 0;int right = array.length - 1;// 这里必须是 <=while (left <= right) {int mid = (left + right) / 2;if (array[mid] >= key) {right = mid - 1;}else {left = mid + 1;}}return right;
}
2.5、查找第一个等于或者大于key的元素
查找第一个等于或者大于key
的元素,也就是说等于查找key
值的元素有好多个,返回这些元素最左边的元素下标;如果没有等于key
值的元素,则返回大于key
的最左边元素下标。
// 查找第一个等于或者大于key的元素
static int findFirstEqualLarger(int[] array, int key) {int left = 0;int right = array.length - 1;// 这里必须是 <=while (left <= right) {int mid = (left + right) / 2;if (array[mid] >= key) {right = mid - 1;}else {left = mid + 1;}}return left;
}
2.6、查找第一个大于key的元素
查找第一个等于key
的元素,也就是说返回大于key
的最左边元素下标。
// 查找第一个大于key的元素
static int findFirstLarger(int[] array, int key) {int left = 0;int right = array.length - 1;// 这里必须是 <=while (left <= right) {int mid = (left + right) / 2;if (array[mid] > key) {right = mid - 1;}else {left = mid + 1;}}return left;
}
3、二分查找变种总结
// 这里必须是 <=
while (left <= right) {int mid = (left + right) / 2;if (array[mid] ? key) {//... right = mid - 1;}else {// ... left = mid + 1;}
}
return xxx;
二分查找变种较多,不过它们的“套路”是一样的,以上代码就是其套路,如何快速写出二分查找的代码,只需按照以下步骤即可:
1、首先判断出是返回left,还是返回right
因为我们知道最后跳出while (left <= right)
循环条件是right < left
,且right = left - 1
。最后right
和left
一定是卡在"边界值"的左右两边,如果是比较值为key
,查找小于等于(或者是小于)key
的元素,则边界值就是等于key
的所有元素的最左边那个,其实应该返回left
。
以数组{1, 2, 3, 3, 4, 5}
为例,如果需要查找第一个等于或者小于3的元素下标,我们比较的key值是3,则最后left
和right
需要满足以下条件:
我们比较的key
值是3,所以此时我们需要返回left
。
2、判断出比较符号
int mid = (left + right) / 2;
if (array[mid] ? key) {//... right = xxx;
}
else {// ... left = xxx;
}
也就是这里的if (array[mid] ? key)
中的判断符号,结合步骤1和给出的条件,如果是查找小于等于key的元素,则知道应该使用判断符号>=
,因为是要返回left
,所以如果array[mid]
等于或者大于key
,就应该使用>=
,以下是完整代码
// 查找小于等于key的元素
int mid = (left + right) / 2;
if (array[mid] >= key) {right = mid - 1;
}
else {left = mid + 1;
}
【End】
查看更多面试题内容,请访问《Java最常见200+面试题全解析》,它包含的模块有:
Java、JVM 最常见面试题解析
Spring、Spring MVC、MyBatis、Hibernate 面试题解析
MySQL、Redis 面试题解析
RabbitMQ、Kafka、Zookeeper 面试解析
微服务 Spring Boot、Spring Cloud 面试解析
扫描下面二维码付费阅读
关注下方二维码,订阅更多精彩内容。
转发朋友圈,是对我最大的支持。
面试官:聊一下二分法相关推荐
- 除了简历上的内容还能跟面试官聊啥?
简历在求职过程中起着至关重要的作用.它不仅是求职的敲门砖,也决定着面试官对我们的第一印象.更重要的是,简历凝结了一个求职者全部的闪光点--我是个什么样的人,之前的学习和工作经历,看这份简历就全知道了. ...
- 和腾讯面试官聊了一个小时人生后,我竟意外的收到Java的offer
作为一名深受腾讯游戏"毒害"的90后,以前最大的理想就是到腾讯开发游戏,去看看腾讯游戏的葫芦里到底卖的是什么药,才会让这么多祖国花朵甘愿把时间和金钱都投入到他们研发的游戏中. 去年 ...
- 360oauth token是什么意思_我在BOSS直聘上都和面试官聊了些什么?
岗位描述 信用卡核心系统功能测试,负责测试计划制定,测试设计,测试执行,测试进度掌控,自动化工具建设等工作. 有责任心,执行力强,工作认真细致,逻辑思维强 熟悉linux,oracle或者IBM大型机 ...
- Redis你能跟面试官聊哪些?
简介:以上文章讲述的是[数据库性能调优知识与面试知识(详解四服务器性能剖析)]接下来我总结一下[Redis入门知识点].觉得我还可以的可以加群一起督促学习探讨技术.QQ群:1076570504 个人学 ...
- java 中向文本写入和读取hashmap_就靠这一篇HashMap的讲解,我与头条面试官聊了一个小时。...
预备知识 位运算知识(更多资料私信"学习"免费获取) 位运算操作是由处理器支持的底层操作,底层硬件只支持01这样的数字,因此位运算运行速度很快.尽管现代计算机处理器拥有了更长的指令 ...
- 跟面试官聊到JVM,他99%会让你谈谈这个问题!
本文转载自微信公众号:王磊的博客 但凡问到 JVM(Java 虚拟机)通常有 99% 的概率一定会问:在 JVM 中如何判断一个对象的生死状态? 本文就来聊聊这个问题,判断对象的生死状态的算法有以下几 ...
- 我是怎么跟面试官聊Map集合的
我习惯了无所谓,却不是真的什么都不在乎. 请关注:源码猎人 目录 简介 Map 框架 Map 接口源码解读 Map 内部类Entry接口源码 AbstractMap 抽 ...
- 一个ThreadLocal和面试官大战30个回合
点击关注公众号,Java干货及时送达 开场 杭州某商务楼里,正发生着一起求职者和面试官的battle. 面试官:你先自我介绍一下. 安琪拉:面试官你好,我是草丛三婊,最强中单(妲己不服),草地摩托车车 ...
- 这才是面试官想听的:详解「递归」正确的打开方式
来自:码农田小齐 前言 递归,是一个非常重要的概念,也是面试中非常喜欢考的.因为它不但能考察一个程序员的算法功底,还能很好的考察对时间空间复杂度的理解和分析. 本文只讲一题,也是几乎所有算法书讲递归的 ...
- 面试官:如果让你设计一个消息中间件,如何将其网络通信性能优化10倍以上?【石杉的架构笔记】...
目录 1.客户端与服务端的交互 2.频繁网络通信带来的性能低下问题 3.batch机制:多条消息打包成一个batch 4.request机制:多个batch打包成一个request " 这篇 ...
最新文章
- Python并行编程(八):with语法
- vue 报错unknown custom element解决方法
- 简述configure,pkg-config,pkg_config_path三者的关系
- Spring Social入门–第2部分
- vue django mysql_django2 rest_framework + vue.js + mysql5.6 实现增删改查
- 使用jsoncpp解析json文件
- Redis数据类型详解(五种)
- Oracle临时库数据数据量过大,Oracle临时表空间过大问题解决
- POJ 1325 Machine Schedule 解题报告
- OMS 订单管理系统
- 与时俱进的迅捷多功能转换器
- BOS启动的客户端,打开序时簿只显示一行
- vs2010学习版loadimage();函数载入图片无法加载的问题
- 计算机网络(思科)章节测试总结
- Shader学习建议
- 句法分析-基于CKY的PCFG(概率上下文无法语法)
- 计算广告笔记05-搜索广告与竞价广告
- 今日头条 ANR 优化实践系列分享 - 实例剖析集锦
- bigbird丁鹏_了解bigbird是nlp的又一个重要里程碑
- FPGA实现uart串口协议