二分查找(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]是否等于targetint 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] == targetreturn 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:1010101a^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都是‘ ^运算 ’得来。
转载于:https://www.cnblogs.com/noKing/p/7977018.html
二分查找(Java实现)相关推荐
- 二分查找 java代码实现
文章目录 二分查找java代码 单元测试 二分查找java代码 package csdn.dreamzuora.query;/*** Title: 二分查找* Description:* 时间复杂度: ...
- 数据结构:二分查找 java
为什么80%的码农都做不了架构师?>>> 二分查找的前提是有序存储,利用顺序存储和元素排序 /*** 二分查找,查找成功,返回下标记* @param values* @para ...
- 二分查找(java)
/*** TODO*/ package com.xeezee.array;/*** 二分查找法* * @author luoqinglong* @date 2012-7-30*/ public cla ...
- java二分查找范围区间_二分查找(Java实现)
二分查找:递归实现 public class BinarySearch { /** * @param arr 代查找的数组,需要有序 * @param left 查找区间的左界限 * @param r ...
- [LeetCode] Serch Insert Position (总结二分查找) Java version
原题地址:https://oj.leetcode.com/problems/search-insert-position/: 查找插入口,在使用二分查找发的时候需要注意,与以前不同.在没有找到与tar ...
- c语言实验报告 折半查找法,C语言数组之冒泡排序+折半查找法(二分查找)
冒泡排序算法 将相邻的元素进行两两比较,大的向后"冒", 小的向前"赶". 口诀: N个数字来排队,两两比较小靠前 外层循环N-1(控制需要比较的轮数). 内层 ...
- 二分查找及其bian'zhong
1.二分查找 java public class binarySearch {public static boolean binarysearch(int[] array,int target) {i ...
- “二分查找”算法的时间复杂度
算法的时间复杂度无非就是for.while等包含起来的基本运算单元的循环次数 1.二分查找 二分查找(binary search),也称作折半查找(half-interval search),每次划分 ...
- 二分查找的时间复杂度为什么是O(logN)
二分查找java实现 /*** 二分查找算法:在目标数组中查找是否存在key,存在返回数据下标,不存在返回-1* @param key 要查找的数据* @param arr 需要查找的目标数据* @r ...
最新文章
- python读写二进制文件的方法
- ACL 2019 开源论文 | 使用跨领域语言建模的跨领域命名实体识别
- freetds php mssql 中文乱码,PHP读取mssql json数据中文乱码的解决办法
- 手掌手指分割算法(源码)
- C++之get、getline探究
- ext教程_exe_作者blackant
- silverlight实现图片局部放大效果
- 找不到 查找_当心Excel查找替换错误,别犯“台风致山东全省人死亡”的错误
- 聊聊微服务架构及分布式事务解决方案!
- vb html编程,VB编程:vb打开网页代码
- 基于JavaSwing+MySql的学生信息管理系统
- URL是什么意思 ? URL介绍
- Codeforces 934D - A Determined Cleanup
- 架构师提升技术影响力的三个阶段(一)
- 【Asan】新鲜货:使用ASan检测内存越界问题
- VTK-修改图片的像素
- 开源至上:面试官轮轮虐你?深入剖析
- C++STL库之algorithm库
- win12服务器文件设置只读,如何在Win10系统中更改文件夹的只读或系统属性
- 巨坑 jom makefile debug error 2 报错