二分查找
二分查找思路分析
1.首先确定该数组的中间的下标
mid = (left + right)/2
mid = left +(right -left)/2
2.然后让需要查找的数findval和arr[mid]比较
findval > arr[mid] 说明你要查找的数在mid的右边,因此需要递归的向右查找
findval < arr[mid] 说明你要查找的数在mid的左边,因此需要递归的向左查找
findval == arr[mid] 说明你要查找的数找到了,返回
结束递归的条件:
1.找到就结束递归
2.递归整个数组,仍然没有找到findval,也需要结束递归,当left > right 就需要退出
使用二分查找的前提是数组是有序的
public static int binarySearch(int[] arr,int findval){
if (arr.length == 0)return -1;
return binarySearch(arr,0,arr.length,findval);
}
public static int binarySearch(int[] arr,int left,int right,int findval){
int mid = (left + right)/2;
int midval = arr[mid];
//当 left > right 说明整个数组没有这个值
if (left > right)return -1;
if (findval > midval){
//向右递归
return binarySearch(arr,mid+1,right,findval);
}else if (findval < midval){
//向左递归
return binarySearch(arr,left,mid-1,findval);
}else return mid;
}
当一个有序数组中,有多个相同的数值时,如何将所有的数值都查到
1.在找到mid的时候不要马上返回
2.向mid这个索引值的左边扫描,将所有满足查找值的下标加入到集合中。
3.向mid的这个索引值的右边扫描
4.将集合返回
public static ArrayList<Integer> binarySearchPlus(int[] arr, int left, int right, int findval) {
int mid = (left + right) / 2;
int midval = arr[mid];
//当 left > right 说明整个数组没有这个值
if (left > right) return null;
if (findval > midval) {
//向右递归
return binarySearchPlus(arr, mid + 1, right, findval);
} else if (findval < midval) {
//向左递归
return binarySearchPlus(arr, left, mid - 1, findval);
} else {
ArrayList<Integer> resIndexList = new ArrayList<>();
//向左边扫描
int temp = mid - 1;
while (true) {
if (temp < 0 || arr[temp] != findval) {
break;
}
//否则,就temp放入到集合中
resIndexList.add(temp);
temp -= 1;//temp左移
}
resIndexList.add(mid);
//向右边扫描
temp = mid + 1;
while (true) {
if (temp > arr.length - 1 || arr[temp] != findval) {
break;
}
//否则,就temp放入到集合中
resIndexList.add(temp);
temp += 1;//temp右移
}
return resIndexList;
}
}
在刷题的时候学到了三个模板
模板一
int binarySearch(int[] nums, int target){
if(nums == null || nums.length == 0)
return -1;
int left = 0, right = nums.length - 1;
while(left <= right){
// Prevent (left + right) overflow
int mid = left + (right - left) / 2;
if(nums[mid] == target){ return mid; }
else if(nums[mid] < target) { left = mid + 1; }
else { right = mid - 1; }
}
// End Condition: left > right
return -1;
}
初始条件:left = 0, right = length-1
终止:left > right
向左查找:right = mid-1
向右查找:left = mid+1
LeetCode69题
LeetCode374题
LeetCode33题
模板二
int binarySearch(int[] nums, int target){
if(nums == null || nums.length == 0)
return -1;
int left = 0, right = nums.length;
while(left < right){
// Prevent (left + right) overflow
int mid = left + (right - left) / 2;
if(nums[mid] == target){ return mid; }
else if(nums[mid] < target) { left = mid + 1; }
else { right = mid; }
}
// Post-processing:
// End Condition: left == right
if(left != nums.length && nums[left] == target) return left;
return -1;
}
初始条件:left = 0, right = length
终止:left == right
向左查找:right = mid
向右查找:left = mid+1
LeetCode278题
LeetCode162题
LeetCode153题
模板三
int binarySearch(int[] nums, int target) {
if (nums == null || nums.length == 0)
return -1;
int left = 0, right = nums.length - 1;
while (left + 1 < right){
// Prevent (left + right) overflow
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid;
} else {
right = mid;
}
}
// Post-processing:
// End Condition: left + 1 == right
if(nums[left] == target) return left;
if(nums[right] == target) return right;
return -1;
初始条件:left = 0, right = length-1
终止:left + 1 == right
向左查找:right = mid
插值查找
插值查找原理介绍
1.插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找
2.将折半查找中的求mid索引的公式,low表示左边索引,high表示右边
key就是findval
3.int midindex = low + (high-low) * (key - arr[low])/(arr[high] - arr[low]);
对于数据量大,关键字分布比较均匀的查找表来说,采用插值查找,速度比较快。
关键字分布不均匀的情况下,该方法不一定比二分查找要好
public static int insertSearch(int[] arr,int left,int right,int findval){
//要求数组是有序的 判断是必须的 否则可能会越界
if (left > right || findval < arr[0] || findval > arr[arr.length-1])return -1;
int mid = left + (right - left) * (findval - arr[left]) / (arr[right] - arr[left]);
int midval = arr[mid];
if (findval > midval){
//应该向右边递归
return insertSearch(arr,mid + 1,right,findval);
}else if (findval < midval){
return insertSearch(arr,left,mid - 1,findval);
}else {
return mid;
}
}