二分查找法题解
/**
* 不使用递归的二分查找
*title:binarySearch
*@param arr
*@param key
*@return 关键字位置
*/
public static int binarySearch(int[] arr,int key){
int left = 0;
int right = arr.length - 1;
int mid = 0; //定义middle
//基于升序
if(key < arr[left] || key > arr[right] || left > right){
return -1;
}
while(left <= right){
//mid = (left + right) / 2;
mid = left+(right-left)>>1;
if(arr[mid] > key){
//比关键字大则关键字在左区域
right = mid - 1;
}else if(arr[mid] < key){
//比关键字小则关键字在右区域
left = mid + 1;
}else{
return mid;
}
}
return -1; //最后仍然没有找到,则返回-1
/**
* 使用递归的二分查找
*title:recursionBinarySearch
*@param arr 有序数组
*@param key 待查找关键字
*@return 找到的位置
*/
public static int recursionBinarySearch(int[] arr,int key,int low,int high){
if(key < arr[low] || key > arr[high] || low > high){
return -1;
}
int middle = (low + high) / 2;//初始中间位置
if(arr[middle] > key){
//比关键字大则关键字在左区域
return recursionBinarySearch(arr, key, low, middle - 1);
}else if(arr[middle] < key){
//比关键字小则关键字在右区域
return recursionBinarySearch(arr, key, middle + 1, high);
}else {
return middle;
}
}
旋转数组的最小数字(改造二分法)
分析:
最小值藏在无序的一边
//旋转数组最小值
public static int xzsz(int arr[]){
//二分查找变体
int begin=0;
int end=arr.length-1;
//考虑非旋转数组的情况
if(arr[begin]<arr[end])return arr[begin];
//最后剩2个元素
while(begin+1<end) {
//中心
int half = begin + (end - begin) >> 1;
//找出无序的部分
//中心的值要小于最后一个元素则说明从中心到最后一个这一段有序
//等于的不一定情况 如 2 2 2 3 0 1 1 1 这种
//取arr[half] <= arr[end]的结果System.out.println(xzsz(new int[]{4,4,4,5,3,4})); 结果为4(错误)
//不取等上面情况是跑不通的
//对于取等的情况需要顺序扫面法
if (arr[half] < arr[end]) {//这里说明 half=>end有序 但也存在意外 上面的其他情况
end = half;
}
else{
begin=half;
}
}
return arr[end];
}
在有空窜的有序串数组中查找
除二分查找需掌握的其他知识:
//1、“==”比较两个变量本身存储的值,即两个对象在内存中的首地址。
//2、“equals()”比较字符串中所包含的内容是否相同。
“abc”.equals(str) 与str.equals(“abc”):
最后结论:
"".equals(str)在str为null的时候返回false,
str.equals("")在str为null时会抛空指针异常.
“”是字符串常量,同时也是一个String类的对象,作为对象可以调用String类里的方法。
null 是空常量,不能调用任何的方法,否则会出现空指针异常,null常量可以给任意的引用数量类型赋值。
//int compareTo(String anotherString)说明:
//如果第一个字符和参数的第一个字符不等,结束比较,返回第一个字符的ASCII码差值。
//如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至不等为止,返回该字符的ASCII码差值。
// 如果两个字符串不一样长,可对应字符又完全一样,则返回两个字符串的长度差值。
//在有空字符串的有序字符串数组中查找
public static int find(String []arr,String str){
//["a","","ab","ac","","ad","b","","ba"]
//有序数组查找首先想到 二分法
int begin=0;
int end=arr.length-1;
if(str.equals(""))
return -1;
while(begin<=end){
int half=begin+(end-begin)>>1;
//1、“==”比较两个变量本身存储的值,即两个对象在内存中的首地址。
//2、“equals()”比较字符串中所包含的内容是否相同。
//当中心为空串时需要处理:++ 或者-- 来找到一个非空的串
while(arr[half].equals("")){
++half;
//注意
if(half>end){
return -1;
}
}
//int compareTo(String anotherString)说明:
//
//如果第一个字符和参数的第一个字符不等,结束比较,返回第一个字符的ASCII码差值。
//如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至不等为止,返回该字符的ASCII码差值。
// 如果两个字符串不一样长,可对应字符又完全一样,则返回两个字符串的长度差值。
if(arr[half].compareTo(str)>0){// 这里是 half位置的串要大于str
end=half-1;
}
else if(arr[half].compareTo(str)<0){
begin=half+1;
}
else{
return half;
}
}
return -1;
}