二分查找的变种(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,然后查找 一个数是否在数据序列中,若是,则返回在序列中的第几个位置. 首先可能第一个想到的就是按照顺序,从前到后一个一个进行查找,直到找到为止,若最后都没有,则说明 ...
随机推荐
- JVM笔记4-对象的创建
1.对象的创建过程: 1.new 类名 2.根据new的参数在常量池中定位一个类的符号的引用. 3.如果没找到这个符号的引用,说明类还没有被加载.则进行类的加载,解析和初始化 4.虚拟机为对象分配内存 ...
- 创建基于MailKit和MimeKit的.NET基础邮件服务
邮件服务是一般的系统都会拥有和需要的功能,但是对于.NET项目来说,邮件服务的创建和使用会较为的麻烦..NET对于邮件功能提供了System.Net.Mail用于创建邮件服务,该基础服务提供邮件的基础 ...
- ap module omap4460
http://gitorious.org/ap-module-omap4460 Dashboard Register Login Activities Projects Teams ap module ...
- javascript 学习笔记 三大特性
<script type="text/javascript"> //封装 function Person (name,age,sal){ this.name=name; ...
- java重写和重载
方法的重载: 在一个类中的两个或两个以上的方法,他们方法名相同但是参数列表不同,这种方式称为方法的重载,方法的重载是实现多态性的方式之一. 参数列表不同指的是参数的个数不同或相同的个数但顺序不同或者类 ...
- ReferenceError: Error #1065: 变量 dataGridArray 未定义
1.错误描述 ReferenceError: Error #1065: 变量 dataGridArray 未定义. at global/flash.utils::getDefinitionByName ...
- org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException
1.错误原因 org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't ...
- spring配置datasource三种方式及具体信息
1.使用org.springframework.jdbc.datasource.DriverManagerDataSource说明:DriverManagerDataSource建立连接是只要有连接就 ...
- 异常-----freemarker.template.TemplateException:Error executing macro:mainSelect
1.错误描述 freemarker.template.TemplateException:Error executing macro:mainSelect require parameter:id i ...
- 【CF17E】Palisection(回文树)
[CF17E]Palisection(回文树) 题面 洛谷 题解 题意: 求有重叠部分的回文子串对的数量 所谓正难则反 求出所有不重叠的即可 求出以一个位置结束的回文串的数量 和以一个位置为开始的回文 ...