大纲
- 二分查找
- 插值查找
- 斐波那契查找
tips:数组查找的前提是数组有序
一、二分查找
/** * 找到中间位置,然后递归前后两个部分 */ private static int binarySearch(int[] arr,int target,int begin,int end){ if (end>=begin) { int mid = (begin+end)/2; if (arr[mid]>target) { return binarySearch(arr,target,0,mid-1); }else if(arr[mid]<target){ return binarySearch(arr,target,mid+1,end); }else{ return mid; } } return -1; }
二、插值查找
/** * 中值有一定自适应性,适用于数值分布均匀的数组,比如等差数列 */ private static int insertSearch(int[] arr,int target,int begin,int end){ if (end>=begin && target<=arr[end] && target>=arr[begin]) { int mid = begin+(end-begin)*(target-arr[begin])/(arr[end]-arr[begin]); if (arr[mid]>target) { return binarySearch(arr,target,0,mid-1); }else if(arr[mid]<target){ return binarySearch(arr,target,mid+1,end); }else{ return mid; } } return -1; }
三、斐波那契查找
/** * 不用2分查找而是根据黄金分割点查找 */ private static int fibSearch(int[] arr,int target){ int[] fib = getFib();//获取一个斐波那契数列 int fibIndex = 0; while (fib[fibIndex] < arr.length) { fibIndex++; } //创建一个新数组,将原来的arr移动到新的数组中,新数组长度为斐波那契数列中的数,长度原来的长度的部分用原数组中最大的补齐 int[] temp = new int[fib[fibIndex]]; for (int i = 0; i < fib[fibIndex]; i++) { if (i>arr.length-1) { temp[i] = arr[arr.length-1]; }else{ temp[i] = arr[i]; } } //查找 int left = 0; int right = arr.length-1; while (right>=left) { //斐波那契数列F[K] = F[K-1] + F[K-2] //因此在前半段(较长的一段)中,再次分割点就是F[K-1],因后半段(较短的一段)中,再次分割点就是F[K-2] //建议自己画图,比较好理解 int mid = left+fib[fibIndex-1]-1; if (temp[mid]>target) { right = mid-1; fibIndex-=1; }else if(temp[mid]<target){ left = mid+1; fibIndex-=2; }else { //每次查找都在后半部分,mid是有可能计算出来>right的(right一直是arr的最后一个元素指针) //出现这种情况返回right即可,right因为后面都是arr[arr.length-1]的值 if (mid>right) { return right; }else{ return mid; } } } return -1; } public static int[] getFib(){ int[] fib = new int[20]; fib[0] = 1; fib[1] = 1; for (int i = 2; i < fib.length; i++) { fib[i] = fib[i-1]+fib[i-2]; } return fib; }