二分查找(Java实现)
二分查找:递归实现
public class BinarySearch {
/**
* @param arr 代查找的数组,需要有序
* @param left 查找区间的左界限
* @param right 查找区间的右界限
* @param target 待查找的值
* @param <T> 泛型
* @return <p>在arr中[left...right]左闭右闭区间查找target, 找到了就返回该下角标,没找到则返回-1.<p/>
*/
public static <T extends Comparable<? super T>> int search(T[] arr, int left, int right, T target) {
if (left > right) return -1;//递归结束了都没找到,返回-1.
int mid = left + (right - left) / 2; // 二分,arr[mid]作为比较的基准值。
if (arr[mid].compareTo(target) == 0) {//如果相等,说明找到
return mid;
} else if (arr[mid].compareTo(target) < 0) {//如果中间的比target小,则在右半边找
return search(arr, mid + 1, right, target);
} else {////如果中间的比target大,则在左半边找
return search(arr, left, mid - 1, target);
}
}
public static <T extends Comparable<? super T>> int search(T[] arr, T target) {
return search(arr, 0, arr.length - 1, target);
}
public static void main(String[] args) {
Integer[] arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};//二分查找需要是有序的数组
int ret = search(arr, 11);
System.out.printf("下角标是:%d\n", ret);
}
}
二分查找:非递归实现
public class BinarySearch {
public static <T extends Comparable<? super T>> int search(T[] arr, T target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {//从[left ... right] 左闭右闭区间找,当left==right时,就是在判断arr[left]是否等于target
int mid = left + (right - left) / 2;
if (arr[mid].compareTo(target) < 0) {//如果中间的比target还小,那么到右半边去找
left = mid + 1;
} else if (arr[mid].compareTo(target) > 0) {//如果中间的比target大,那么到左半边去找
right = mid - 1;
} else {//如果 arr[mid] == target
return mid;
}
}
//如果没找到
return -1;
}
public static void main(String[] args) {
Integer[] arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};//二分查找需要是有序的数组
int ret = search(arr, 11);
System.out.printf("下角标是:%d\n", ret);
}
}
二分查找:求mid时除以2的bug问题
比如left = 1256648431, right = 1742321453 那么相加后就会上溢,得到结果 -1295997412, 除以2之后就是 -647998706,显然这个结果是不对的。
下面介绍三种方法,可以计算出正确的结果 1499484942
public class BinarySearch {
public static void main(String[] args) {
int a = 1256648431;
int b = 1742321453;
long c = (long) a + b;
System.out.printf("a + b 应该等于 %d ", c);//a + b 应该等于 2998969884 ,正确
System.out.printf("(a + b)/2 应该等于 %d\n\n", c / 2);//(a + b)/2 应该等于 1499484942 ,正确
System.out.println("整数int型用普通除法");
System.out.printf("a + b 等于 %d ", a + b);// -1295997412 ,溢出
System.out.printf("(a + b)/2 等于 %d\n\n", (a + b) / 2);// -647998706 ,溢出
System.out.println("整数int型用逻辑右移代替除法");
System.out.printf("a + b 等于 %d ", a + b);// -1295997412 ,溢出
System.out.printf("(a + b)>>>1 等于 %d\n\n", (a + b) >>> 1);// 1499484942 ,正确
System.out.println("整数int型用位运算技巧代替除法");
System.out.printf("a + b 等于 %d ", a + b);// -1295997412 ,溢出
System.out.printf("(a & b) + (a ^ b) >> 1 等于 %d\n\n", (a & b) + ((a ^ b) >> 1));// 1499484942 ,正确
}
}
最后一种情况,请查看该博客:用位运算求两个整型数的平均值(避免溢出)
给女朋友讲最后一种情况时的笔记:
目的:两个二进制数,对应位置进行相加,求出每项的项系数,也就是每位结果。
根据规律,分为两种情况。
1.对应位不同,其中一个为1,另一个为0
2.对应位相同,即同为1,或同为0
设a:1100110,b:1010101. 那么a + b = 2110211.(先不考虑进位)
处理情况1:去找规律,发现,情况为1时,相加总为1,相当于异或运算。对于情况2,异或运算总为0,不会被影响到。
处理情况2:再去找规律,发现,情况为2时,两数相加的结果要么是0,要么是2。结果总是‘&运算’结果的2倍。对于情况1,&运算结果总得到0,不会被影响到。 a:1100110
b:1010101
a^b:0110011 0 1 4 5 找到了这些项的系数
a&b:1000100 2 3 6 找到了这些项的系数
但上面这个与运算得出来的并不是真正的项系数,而是对应位置项系数的一般。所以 * 2后得
:2000200(先不考虑进位)
所以sum = (a & b) * 2 + (a ^ b)
sum / 2 = (a & b) + (a ^ b) / 2 (后续再把这个除法改成右移运算)
----------------------------------------------------------
或者换一种说法。
设a:1100110,b:1010101. 那么a + b = 2110211.(先不考虑进位)
对于a + b = 2110211.其中的2都是'&运算' 乘2得来,其中的1都是‘ ^运算 ’得来。
二分查找(Java实现)的更多相关文章
- 数据结构之二分查找——Java语言实现
场景描述:给出一个数据序列长度为N,然后查找 一个数是否在数据序列中,若是,则返回在序列中的第几个位置. 首先可能第一个想到的就是按照顺序,从前到后一个一个进行查找,直到找到为止,若最后都没有,则说明 ...
- 数据结构和算法设计专题之---二分查找(Java版)
1.前提:二分查找的前提是需要查找的数组必须是已排序的,我们这里的实现默认为升序 2.原理:将数组分为三部分,依次是中值(所谓的中值就是数组中间位置的那个值)前,中值,中值后:将要查找的值和数组的中值 ...
- 二分查找(Java)
二分查找的前提的要查找的数组必须有序. 代码如下: 程序1 public class source { public int binary_sort(int[] array, int item) { ...
- 二分查找-Java版
/** * * 二分查找算法 * * * * @param srcArray 有序数组 * * @param target 查找元素 * * @return srcArray数组下标,没找到返回-1 ...
- 二分查找java实现
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列. 二分查找思路非常简单,由粗暴的遍历查找改为 ...
- 快速排序和二分查找(Java)
import java.util.Arrays; public class Main { public static void main(String[] args) { int[] data = { ...
- 二分查找java代码
public int find(long searchKey){ int i; int begin = 0; int end = nElems - 1; while(true){ i = (begin ...
- 从三数之和看如何优化算法,递推-->递推加二分查找-->递推加滑尺
人类发明了轮子,提高了力的使用效率. 人类发明了自动化机械,将自己从重复的工作中解脱出来. 提高效率的方法好像总是离不开两点:拒绝无效劳动,拒绝重复劳动.人类如此,计算机亦如是. 前面我们说过了四数之 ...
- Java实现的二分查找算法
二分查找又称折半查找,它是一种效率较高的查找方法. 折半查找的算法思想是将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小 于该中点 ...
随机推荐
- 基础--Linux环境下一键部署 lnmp
1. 通过x-shell 或者 putty 登录服务器 2. 下载lnmp一键安装包 >wget -c http://soft.vpser.net/lnmp/lnmp1.4.tar.gz # ...
- 利用ffmpeg做视频解码的顺序
这几天在实验室捣鼓着用ffmpeg做视频解码,终于把数据解出来了,虽然还没有做显示部分,不知道解码解得对不对,但料想是不会有什么问题了.回头看看这几天的工作,其间也遇到了不少问题,主要还是对ffmpe ...
- Linux查看用于终止进程命令
Linux查看用于终止进程命令 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ ps PID TTY TIME CMD 2576 pts/0 00:00:00 ...
- Educational Codeforces Round37 E - Connected Components?
#include <algorithm> #include <cstdio> #include <iostream> #include <queue> ...
- 【原】spring boot添加cros全局过滤器
新增一个过滤器类并实现filter接口 public class CorsFilter implements Filter { final static org.slf4j.Logger logger ...
- n人围成一圈报数
题目:有n个人围成一圈,顺序排号.从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位 思路:用一个数组存这n个人,里面的初始状态全设为1,表示都还在圈子里面. ...
- Android破解学习之路(七)—— 乐秀视频编辑 内购破解 专业版 价值25元的破解
按照之前的支付宝破解,搜索9000的十六进制,之后... 但是,这样测试的时候,没有破解成功,便是继续研究 搜索关键字支付失败,之后找到了指定的smali文件,观察了许久,发现里面有个switch跳转 ...
- Spring Data(一)概念和仓库的定义
Spring Data(一)概念和仓库的定义 Spring Data的主要任务是为数据访问提供一个相似的.一致的.基于Spring的编程模型,同时又保留着下面各个数据存储的特征.它使得使用数据访问技术 ...
- 新的一年新的变化!IT的大变天
今天是一个特别的日子,祝女神朋友们,节日快乐,早点下班! 新的一年,大家又忙碌在加班加点的堆代码中,bug的陪伴使我快乐使我忧伤,想想想,也奋斗了五六百的岁月,实习期向往大城市的公司,梦想着有一天与自 ...
- 【CF17E】Palisection(回文树)
[CF17E]Palisection(回文树) 题面 洛谷 题解 题意: 求有重叠部分的回文子串对的数量 所谓正难则反 求出所有不重叠的即可 求出以一个位置结束的回文串的数量 和以一个位置为开始的回文 ...