二分查找的变种(Java实现)
普通二分查找:
先回顾一下普通的二分查找
注意:二分查找有这样一个问题:当数组中数有重复时,比如 {3,3,3,3} 这个数组,二分查找3时,返回的是arr[1],也就是说二分查找并不会返回3第一次出现的位置0。
public class BinarySearch {
public static <T extends Comparable<? super T>> int search(T arr[], T value) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = (left & right) + ((left ^ right) >> 1);
if (arr[mid].compareTo(value) == 0) {
return mid;
} else if (arr[mid].compareTo(value) > 0) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
} public static void main(String[] args) {
Integer[] arr = new Integer[]{1, 3, 3, 6, 7, 9}; //-1
System.out.println(search(arr, 0)); //0
System.out.println(search(arr, 1)); //5
System.out.println(search(arr, 9)); //-1
System.out.println(search(arr, 10)); //2
System.out.println(search(arr, 3));
}
}
二分变种:findFirst函数
在普通二分查找中,在[left....right]左闭右闭区间中查找,如果找到了值为value的元素就认为找到了。而在这个findFirst函数中就不是如此,在[left....right]左闭右闭区间中查找,当找到值等于value的元素后,不是让right = mid - 1,而是让right = mid,继续在[left....right]左闭右闭区间中查找。最终left== right时就退出循环。
退出循环后可能找到了value值,也有可能是循环遍历完整个数组后都没找到value,而退出循环。
所以退出循环后还要在判断一下是那种情况。
public class BinarySearch {
public static <T extends Comparable<? super T>> int findFirst(T arr[], T value) {
int left = 0;
int right = arr.length - 1;
//当left>=right时退出,这里的“=”情况与二分不同
while (left < right) {
int mid = (left + right) >> 1;
if (arr[mid].compareTo(value) < 0) {
left = mid + 1;
} else {
right = mid;
}
}
// 上面循环遍历完后。是找到了value值?还是没找到value值?判断一下。
if (arr[left] == value) {
return left;
} else {
return -1;
}
} public static void main(String[] args) {
Integer[] arr = new Integer[]{1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 7, 9}; //-1
System.out.println(findFirst(arr, 0)); //0
System.out.println(findFirst(arr, 1)); //12
System.out.println(findFirst(arr, 9)); //-1
System.out.println(findFirst(arr, 10)); //1
System.out.println(findFirst(arr, 3));
}
}
二分变种:fewer函数
介绍
给定一个数组,和一个变量value,从数组中找出值最接近value值而且比value小的那个数。比如 arr = {11,22,22,33 ,33,33,44,54} value = 33。 22最接近value,而且比value小。
所以答案是2 ( 22在数组arr中的下角标 ) 。
如果没找到比value小的数,那么输出 -1。
解决思路
用二分查找方法。每次用 arr[mid] 来与value进行比对。小、等于,去左边找;大,去右边找。可能上一句的“等于”的情况你不太理解。普通二分查找是找出arr[mid] == value,而fewer函数是为了找出比value小的数,所以尽管arr[mid] == value,还得继续去左边找更小的值。
例子
代码
public class BinarySearch {
public static <T extends Comparable<? super T>> int fewer(T arr[], T value) {
int left = 0;
int right = arr.length - 1;
//当left > right 时退出
while (left <= right) {
int mid = (left & right) + ((left ^ right) >> 1);
if (value.compareTo(arr[mid]) <= 0) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return right;
} public static void main(String[] args) {
Integer[] arrF = new Integer[]{21, 23, 25, 25, 31, 34, 37, 39, 52, 63}; //3
System.out.println(fewer(arrF, 30));
}
}
二分变种:greater函数
二分查找的变种(Java实现)的更多相关文章
- 二分查找BinarySearch(Java)
二分查找(折半查找)BinarySearch 二分查找 一组排好顺序的数,查找其中的一个数(value)的位置,按照数组(int[] a)存放这组数据,数组的索引所指的位置就是需要查找的数,用三个变 ...
- 经典算法二分查找循环实现Java版
二分查找 定义 二分查找(Binary Search)又称折半查找,它是一种效率较高的查找方法. 要求 (1)必须采用顺序存储结构 (2)必须按关键字大小有序排列 查找思路 首先将给定值K,与表中中间 ...
- 二分查找算法,java实现
二分查找算法是在有序数组中用到的较为频繁的一种算法. 在未接触二分查找算法时,最通用的一种做法是,对数组进行遍历,跟每个元素进行比较,其时间复杂度为O(n),但二分查找算法则更优,因为其查找时间复杂度 ...
- 二分查找算法(JAVA)
1.二分查找又称折半查找,它是一种效率较高的查找方法. 2.二分查找要求:(1)必须采用顺序存储结构 (2).必须按关键字大小有序排列 3.原理:将数组分为三部分,依次是中值(所谓的中值就是数组中间位 ...
- 二分查找算法的java实现
1.算法思想: 二分查找又称折半查找,它是一种效率较高的查找方法. 时间复杂度:O(nlogn) 二分算法步骤描述: ① 首先在有序序列中确定整个查找区间的中间位置 mid = ( low + ...
- Leetcode 153. Find Minimum in Rotated Sorted Array -- 二分查找的变种
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...
- 二分查找法(java版)
二分查找法也称为折半查找法,在有序的序列中使用二分法可以提高程序的执行效率. 典型的二分查找法代码 public int binarySearch1(int[] arr,int target){ in ...
- 【15】-java实现二分查找
二分查找在面试中经常被遇到,这个方法十分优雅 介绍 二分查找可以解决(预排序数组的查找)问题:只要数组中包含T(即要查找的值),那么通过不断缩小包含T的范围,最终就可以找到它.一开始,范围覆盖整个数组 ...
- 数据结构之二分查找——Java语言实现
场景描述:给出一个数据序列长度为N,然后查找 一个数是否在数据序列中,若是,则返回在序列中的第几个位置. 首先可能第一个想到的就是按照顺序,从前到后一个一个进行查找,直到找到为止,若最后都没有,则说明 ...
随机推荐
- 深度学习菜鸟的信仰地︱Supervessel超能云服务器、深度学习环境全配置
并非广告~实在是太良心了,所以费时间给他们点赞一下~ SuperVessel云平台是IBM中国研究院和中国系统与技术中心基于POWER架构和OpenStack技术共同构建的, 支持开发者远程开发的免费 ...
- 一句Python,一句R︱pandas模块——高级版data.frame
先学了R,最近刚刚上手python,所以想着将python和R结合起来互相对比来更好理解python.最好就是一句python,对应写一句R. pandas可谓如雷贯耳,数据处理神器. 以下符号: = ...
- Java中File类总结
/** * @Title:JavaFile.java * @Package:com.yhd.chart.model * @Description:File类测试 * @author:Youhaidon ...
- linux下自动加载设备驱动程序模块
假设你的设备驱动程序为:yourdrivername.ko 1 cp yourdrivername.ko /lib/modules/"version"/kernel/driver ...
- C#之AES256位加密解密
密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分 ...
- JavaScript遍历table
JavaScript遍历table 1.说明 遍历表格中的某行某列,并打印其值 2.实现源码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML ...
- directX根据设备类GUID查询所属的filter
hr = m_pSysDevEnum->CreateClassEnumerator(*clsid, &pEnumCat, 0); ASSERT(SUCCEEDED(hr)); ...
- 一款PHP环境整合工具—VertrigoServ介绍
Vertrigo简介 VertrigoServ 是一个Windows平台下的非常专业的.易于安装的免费网络开发环境,它集成了Apache, PHP, MySQL, SQLite, SQLiteMana ...
- String.valueOf(Thread.currentThread().getContextClassLoader().getResource("")) 获取项目的绝对路径(shiro项目中来的八)
一,上代码 String.valueOf(Thread.currentThread().getContextClassLoader().getResource("")) file: ...
- 浅谈java编译机制和运行机制
源文件和字节码的组成方式 源文件: 拓展名后跟java的文件即java的源文件. Java 源码编译由以下三个过程组成: 1.分析和输入到符号表 2.注解处理 3.语义分析和生成class文件 流程图 ...