查找算法
插值查找
插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找。
将折半查找中的求mid索引的公式, left表示左边索引, right表示右边索引.
int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left])
代码实现
/**
* 插值查找
* 注意:插值查找要求数组是有序的
* @param arr 数组
* @param left 左边索引
* @param right 右边索引
* @param findVal 查找的值
* @return
*/
public static int insertValueSearch(int[] arr,int left,int right,int findVal){
//注意findVal < arr[0] || findVal > arr[arr.length - 1] 必须需要
//否则得到的mid值可能越界;
if(left > right || findVal < arr[0] || findVal > arr[arr.length - 1]){
return -1;
}
//求出mid,自适应写法
int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
int midVal = arr[mid];
if(findVal > midVal){
return insertValueSearch(arr,mid + 1,right,findVal);
}else if(findVal > midVal){
return insertValueSearch(arr,left, mid - 1,findVal);
}else{
return mid;
}
}
二分查找的思路分析
使用二分查找前提是 必须是有序的数组
1.首先确定该数组的中间的下标mid = (left+right)/ 2
2.然后让需要查找的数findval和arr[mid]比较
3. 1 findval>arr[mid],说明你要查找的数在mid的右边,因此需要递归的向右查找2.2 findval<arr[mid],说明你要查找的淡在mid的左边,因此需要递归的向左查找2.3 findvalmm arr[mid]说明找到,就返回
什么时候我们需要结束递归
1)找到就结束递归
2)递归完整个数组,仍然没有找到需要查找的值,也需要结束递归。当左索引 > 右索引就需要退出
代码实现
/**
* 二分查找
* 注意:二分查找的前提 必须是该数组是有序的
* @param arr 数组
* @param left 左边索引
* @param right 右边索引
* @param findVal 查找的值
* @return
*/
public static ArrayList<Integer> binarySearchYH(int []arr, int left, int right, int findVal){
//当 left > right时,说明递归整个数组,但是没有找到
if(left > right){
return new ArrayList<>();
}
int mid = (left + right) / 2;
int midVal = arr[mid];
if (findVal > midVal){ //向右递归
return binarySearchYH(arr,mid + 1,right,findVal);
} else if(findVal < midVal){ //向左递归
return binarySearchYH(arr,left,mid - 1,findVal);
} else {
//思路分析
//在找到mid 素引值,不要马上返回
//向mid索引值的左边扫描,将所有满足findVal的元素的下标,加入到集合ArrayList
//向mid索引值的右边扫描,将所有满足findVal的元素的下标,加入到集合ArrayList
//将Arraylist返回
ArrayList<Integer> list = new ArrayList<>();
//向左扫描所有满足条件的加入集合
int temp = mid - 1;
while (true){
//当向左扫描时,下标小于0时或者值与查找值不符时退出
if (temp < 0 || arr[temp] != findVal){
break;
}
list.add(temp);
temp -= 1;//向左查找 左移
}
list.add(mid);
//向右扫描所有满足条件的加入集合
temp = mid + 1;
while (true){
//当向右扫描时,下标大于数组长度-1时时或者值与查找值不符时退出
if (temp > arr.length - 1 || arr[temp] != findVal){
break;
}
list.add(temp);
temp += 1;//向右查找右移
}
return list;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)