java常用查找算法
java常用查找算法
线性查找
/**
* 找到一个就返回
* @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;
}