有关于二分搜索的常见问题(java实现)
前言:
二分搜索是一个非常常见的面试题目,它具有非常广泛的用途。熟练的掌握二分搜索的基本形式和他的变式是非常重要的。接下来我们将使用java实现一些常见的有关二分搜索的问题。
具体内容:
1.二分搜索的基本形式:在一个有序的数组中查找k,如果k存在的话就返回k的下标,否则就返回-1
基本的二分搜索要注意以下几个问题:
(1)边界条件:如果k比array[0]小,或者k比array[length-1]大的话,那就说明k是不存在的;如果数组的长度为0那么也说明k是不存在的
(2)middle的求法:middle = low+(high-low)/2
以下是具体代码:
//在一个有序无重复数组中找到和k相等的数的位置,找不到就返回-1
public static int binarySearchUnique(int[] array, int k){
int length = array.length;
int low = 0, high = length-1;
if(low>high || k<array[low]||k>array[high]){
return -1;
}
while(low<=high){
int middle = low+(high-low)/2;
if(array[middle] == k){
return middle;
}else{
if(array[middle]>k){
low = middle +1;
}else{
high = middle -1;
} }
}
return -1;
}
2.二分搜索进阶版:在一个有序有重复的数组中找到大于等于k的最小下标,如果不存在就返回-1
思想:(1)将k和array[middle]的值进行对比,如何前者更大的话,那么说明low=middle+1;否则说明high=middle;这里为什么不是high=middle-1,因为有可能array[middle-1]比k要小,那么这个时候high就不是大于等于k的元素的最小下标所在的上限。
(2)外层循环条件由low<=high;改成了low<high;因为如果是low等于high的话,由于high=middle,那么有可能会陷入死循环
(3)跳出循环的条件是low等于high。此时返回的low就是所求的值。
注意的点:(1)边界情况的判断:数组的长度要大于0
(2)循环的跳出条件是low<high
(3)最后的low就是所求的值
//在一个有序有重复的数组中找到和k相等的数的最小下标,找不到就返回-1
//search the position for the number which is the first number of <=k
public static int binarySearchMany(int[] array, int k){
int high = array.length -1;
int low = 0;
if(low>high||k>array[high]){
return -1;
}
while(low<high){
int middle = low+(high-low)/2;
if(array[middle]<k){
low = middle + 1;
}else{
high = middle;
}
}
return low;
}
3.二分搜索进阶版:在一个有序的无重复的前后轮转的数组中找到k的位置,如果k不存在的话返回-1
思想:将k值和array[middle],array[high]以及array[low]分别比较:
当 k==array[middle]时,说明找到了
当array[middle]<k<=array[high],说明low=middle+1;
当array[middle]<k&&array[high]<k,我们只能知道high = high -1;
当array[low]<=k<array[middle], 说明high = middle -1;
当array[low]>k&&array[middle]>k,我们只能知道low = low+1;
//给定一个有序递增数组,不含有重复元素,但是这个有序数组发生了rotate,用二分查找找到k的位置,k不存在的话返回1
public static int binarySearchRotate(int[] array, int k){
int length = array.length -1;
int low = 0, high = length;
if(low>high){
return -1;
}
while(low<=high){
int middle = low+(high - low)/2;
if(array[middle]==k){
return middle;
}else{
if(array[low]<=k&&array[middle]>k){
high = middle -1;
}else if(array[low]>k&&array[middle]>k){
low += 1;
}else if(array[high]>=k&&array[middle]<k){
low = middle+1;
}else{
high = high-1;
} }
}
return -1; }
4.二分搜索进阶版:在一个有序的无重复的数组中找到满足array[i]=i的最小下标
思想:
(1)array[middle]>=middle,那么说明下标大于middle的那部分数据都是不可能的
(2)array[middle]<=middle, 那么说明下标小于middle的那部分数据都输不可能的
边界:如果array[0]>0的话,那么是不可能找到的,同理array[length-1]也不能小于length;数组的长度要大于0
//给定一个有序递增数组arr,其中不含有重复元素,请找到满足arr[i]==i条件的最左的位置。如果所有位置上的数都不满足条件,返回-1
public static int binarySearchIndex(int[] array){
int low = 0, high = array.length-1;
if(low>high||array[low]>0||array[high]<high){
return -1;
}
while(low<high){
int middle = low +(high-low)/2;
if(array[middle]>=middle){
high = middle - 1;
}else if(array[middle]<middle){
low = middle + 1;
}
}
if(array[low]==low){
return low;
}
return -1;
}
测试:
对以上的代码进行测试:
1.先写出朴素的搜索函数:
// the common method to find the k
public static int findk(int[] array, int k){
for(int i = 0; i<array.length; i++){
if(array[i]==k){
return i;
}
}
return -1;
}
// the common method to find the first value which is >=k
public static int findFirstValue(int[] array, int k){
for(int i = 0; i<array.length; i++){
if(array[i]>=k){
return i;
}
}
return -1;
}
//the common method to find first number which satisfy array[i] = i
public static int findFirstIndex(int[] array){
for(int i=0; i<array.length; i++){
if(array[i]==i){
return i;
}
}
return -1;
}
2.进行测试
public static void main(String args[]){
int N = 1000000;
Random rand = new Random();
double same = 0.0;
while(N>0){
int n = rand.nextInt(50)+1;
int k = rand.nextInt();
int[] array = new int[n];
for(int i = 0; i<n; i++){
array[i] = rand.nextInt();
}
Arrays.sort(array);
int position;
position = binarySearchMany(array, k);
int position2 = findFirstValue(array, k);
if(position == position2){
same++;
}else{
System.out.println(k);
for(int i=0; i<n; i++){
System.out.print(array[i]+" ");
}
System.out.println();
System.out.println(position);
System.out.println(position2);
}
N--;
}
double ratio = same/1000000;
System.out.println(ratio);
}
3.经过测试以上代码皆为正确代码
有关于二分搜索的常见问题(java实现)的更多相关文章
- [Spring常见问题]java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
这个问题是因为部署在tomcat下的项目中没有springweb包 但是问题来了,但是我的项目中有呀,maven都引了呀,然后我就懵B啦!看到这个博客我就豁然开朗了:http://my.oschina ...
- JAVA面向对象初步知识总结:封装、继承、多态
1.封装 把数据和方法包装进类中,以及具体实现的隐藏,常共同被称作是是封装.其结果是一个同时带有特征和行为的数据类型.所谓具体实现的隐藏是通过访问权限控制实现的.JAVA 子类重写继承的方法时,不可以 ...
- Java基础面试题总结
目录 索引 Java基础知识篇 Java web基础知识总结 Java集合篇常见问题 Java基础知识篇 面向对象和面向过程的区别 面向过程: 优点:性能比面向对象高,因为类调用时需要实例化,开销比较 ...
- java构建工具——ant使用
Ant是跨平台的构建工具,它可以实现项目的自动构建和部署等功能.在本文中,主要让读者熟悉怎样将Ant应用到Java项目中,让它简化构建和部署操作. 一.安装与部署 1.1 下载 下载地址:https: ...
- day01<计算机基础知识&Java语言基础>
计算机基础知识(计算机概述) 计算机基础知识(软件开发和计算机语言概述) 计算机基础知识(人机交互) 计算机基础知识(键盘功能键和快捷键) 计算机基础知识(如何打开DOS控制台) 计算机基础知识(常见 ...
- 【Java】3到5年开发常见的Java面试题
一.Java基础和高级 String类为什么是final的. HashMap的源码,实现原理,底层结构. 反射中,Class.forName和classloader的区别 session和cookie ...
- 2019滴滴java面试总结 (包含面试题解析)
2019滴滴java面试总结 (包含面试题) 本人6年开发经验.今年年初找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.滴滴等公司offer,岗位是既有php也有Java后端开发,最终选择去了滴滴 ...
- 2019头条java面试总结 (包含面试题解析)
2019滴滴java面试总结 (包含面试题) 本人8年开发经验.今年年初找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.滴滴等公司offer,岗位是Java后端开发. 面试了很多家公司,感觉大部分 ...
- 挑战10个最难的Java面试题(附答案)【上】【华为云技术分享】
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/devcloud/article/deta ...
随机推荐
- Mybatis插件原理分析(三)分页插件
在Mybatis中插件最经常使用的是作为分页插件,接下来我们通过实现Interceptor来完成一个分页插件. 虽然Mybatis也提供了分页操作,通过在sqlSession的接口函数中设置RowBo ...
- C++实现最小堆及插入,调整顺序,删除堆顶元素的操作
上次用Java实现了最大堆的封装,这次就来写一下最小堆的实现吧 插入函数的思路: 向堆中插入元素有两种情况,一种是堆为空,那么就让插入值作为根节点即可:另一种是堆不为空,那么此时就要进行判断当前节点与 ...
- tar 压缩和解压缩使用笔记
tar 压缩和解压缩使用笔记 1 文件 1.1 打包 1.1 压缩 $ tar czf myfile.txt.tar.gz ./myfile.txt 1.2 解压缩 解压缩到目录: $ mkdir o ...
- jdbc连接mysql加载驱动程序com.mysql.jdbc.Driver
在开发环境如eclipse,中加载指定数据库的驱动程序.需要下载MySQL支持JDBC的驱动程序mysql-connector-java-5.1.25-bin.jar. 而具体在Java程序中加载驱动 ...
- Linux IPC实践(12) --System V信号量(2)
实践1:信号量实现进程互斥 父子进程执行流程如下: 父进程 子进程 P P O(print) X(print) sleep sleep O(print) X(print) V V sleep slee ...
- 【翻译】在Ext JS和Sencha Touch中创建自定义布局
原文:Creating Custom Layouts in Ext JS and Sencha Touch 布局系统是Sencha框架中最强大和最独特的一部分.布局会处理应用程序中每个组件的大小和位置 ...
- Mac OS X 10.8.4下面XZ Utils(*.tar.xz)压缩解压缩命令工具的安装
主要参考:http://bbs.chinaunix.net/thread-3610738-1-1.html 现在很多找到的软件都是tar.xz的格式的,xz 是一个使用 LZMA压缩算法的无损数据压缩 ...
- Java-HttpServlet
/** * * Provides an abstract class to be subclassed to create * an HTTP servlet suitable for a Web s ...
- UTL_HTTP Call a Web Service and Pass Parameters as Part of the URL
SET DEFINE OFF SET SERVEROUTPUT ON DECLARE req UTL_HTTP.REQ; resp UTL_HTTP.RESP; value VARCHAR2(3276 ...
- Android特效专辑(十二)——仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View
Android特效专辑(十二)--仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View 先来看看这个效果 这是我的在Only上添加的效果,说实话,Only现在都还只是半成品,台面都上不了,怪自己技术 ...