线性查找
/** * 找到一个就返回 * @param arr 数组 * @param value 需要找的数 * @return 找的数的下标,没找到为-1 */ public static int seqSearch(int[] arr, int value) { for (int i = 0; i < arr.length; i++) { if (arr[i] == value) { return i; } } return -1; }
二分查找
递归法(找一个)
/** * 二分查找一个值 * 必须left和right中间有序 * * @param arr 数组 * @param left 左边的索引 * @param right 右边的索引 * @param value 需要查找的值 * @return 值的下标,-1为找不到 */ public static int binary(int[] arr, int left, int right, int value) { if (left > right) { return -1; } int mid = left + (right - left) / 2; int midValue = arr[mid]; // 如果要找的值在右边 if (value > midValue) { // 向右递归 return binary(arr, mid + 1, right, value); } else if (value < midValue) { return binary(arr, left, mid - 1, value); } else { // 等于,返回 return mid; } }
递归法(找多个)
/** * 二分查找多个值 * 必须left和right中间有序 * * @param arr 数组 * @param left 左边的索引 * @param right 右边的索引 * @param value 需要查找的值 * @return 值的下标, null为找不到 */ public static List binary02(int[] arr, int left, int right, int value) { if (left > right) { return null; } int mid = left + (right - left) / 2; int midValue = arr[mid]; // 如果要找的值在右边 if (value > midValue) { // 向右递归 return binary02(arr, mid + 1, right, value); } else if (value < midValue) { return binary02(arr, left, mid - 1, value); } else { List<Integer> ans = new ArrayList<>(); int temp = mid - 1; // 向左扫描 while (true) { if (temp < 0 || arr[temp] != value) { break; } ans.add(temp--); } ans.add(mid); // 向右扫描 temp = mid + 1; while (true) { if (temp > arr.length - 1 || arr[temp] != value) { break; } ans.add(temp++); } return ans; } }
插值查找
public static int insert(int[] arr, int left, int right, int value) { if (left > right || value < arr[0] || value > arr[arr.length - 1]) { return -1; } int mid = left + (right - left) * ((value - arr[left]) / (arr[right] - arr[left])); int midValue = arr[mid]; if (value > midValue) { // 在mid的右边 return insert(arr, mid + 1, right, value); } else if (value < midValue) { // 在mid的左边 return insert(arr, left, mid - 1, value); } else { return mid; } }
斐波那契黄金分割法查找
// 得到斐波那契数列 public static int[] getFibonacci() { int max = 20; int[] f = new int[max]; f[0] = 1; f[1] = 1; for (int i = 2; i < max; i++) { f[i] = f[i - 1] + f[i - 2]; } return f; } public static int fibonacci(int[] arr, int value) { int low = 0; int high = arr.length - 1; // 获取到斐波那契数列分割数值的下标 int k = 0; int mid = 0; int[] f = getFibonacci(); // 拿到k while (high > f[k] - 1) { ++k; } // f[k]可能大于数组长度,扩容 int[] temp = Arrays.copyOf(arr, f[k]); // 需要使用arr数组中最后的数填充 for (int i = high + 1; i < temp.length; i++) { temp[i] = arr[high]; } // 处理拿到k while (low <= high) { // 拿到mid mid = low + f[k - 1] - 1; if (value < arr[mid]) { // 向左 high = mid - 1; --k; } else if (value > arr[mid]) { // 向右 low = mid + 1; k -= 2; } else { // 找到 if (mid <= high) { return mid; } else { return high; } } } return -1; }