实现一个不用除法的二分查找(移位运算符,斐波那契查找)
这边提供两种方案:
1,常规二分查找里面,除法的作用只为了除以2,这个等价于右移1位,故直接更改mid的计算如下:
public static int rank(int key, int[] a) { // 数组必须是有序的 int lo = 0; int hi = a.length - 1; while (lo <= hi) { // 被查找的键要么不存在,要么必然存在于a[lo..hi] 之中 int mid = lo + ((hi - lo) >> 1);// 右移一位 if (key < a[mid]) { hi = mid - 1; } else if (key > a[mid]) { lo = mid + 1; } else return mid; } return -1; }
2,采用斐波那契查找,思路是将二分的mid值定为黄金分割点,数组长度为f(n)-1,左边为f(n-2)-1,中间1,右边为f(n-1)-1,不清楚的可以看我之前的那期斐波那契数,或者百度一下,这边是直接提供解决方案:
public static int fSearch(int[] arr, int key) { int left = 0; int right = arr.length - 1; int[] f = fib(); int k = 0; int mid = 0; while (arr.length > f[k] - 1) { k++; } int[] tmp = Arrays.copyOf(arr, f[k]); for (int i = right + 1; i < tmp.length; i++) { tmp[i] = tmp[right]; } while (left <= right) { mid = left + (f[k - 1] - 1); if (key < tmp[mid]) { right = mid - 1; k--; } else if (key > tmp[mid]) { left = mid + 1; k -= 2; } else if (mid > arr.length - 1) { return arr.length - 1; } else return mid; } return -1; } public static int[] fib() { int[] f = new int[20]; f[0] = 1; f[1] = 1; for (int i = 2; i < MaxSize; i++) { f[i] = f[i - 1] + f[i - 2]; } return f; }