二分查找
/**
* 二分查找
* 数组必须有序
*/
public class BinarySearch {
public static void main(String[] args) {
int arr[] = {3, 4, 5, 5,5,5,6, 7, 8, 9};
ArrayList<Integer> integers = binarySearch2(arr, 0, arr.length, 5);
System.out.println(integers);
}
/**
* 重复的值不能全部找到
*
* @param arr
* @param left 左边的索引
* @param right 右边的索引
* @param findVal 要寻找的值
* @return
*/
public static int binarySearch(int[] arr, int left, int right, int findVal) {
if (left > right) {
return -1;
}
int mid = (left + right) / 2;
int midVal = arr[mid];
if (midVal > findVal) {
return binarySearch(arr, left, mid - 1, findVal);
} else if (midVal < findVal) {
return binarySearch(arr, mid + 1, right, findVal);
} else {
return mid;
}
}
/**
* 有多个相同的值时,如何将所有的数据都找到
* 思路分析:
* 在找到mid索引时不要马上返回
* 向mid的左边扫描,将所有满足 1000 的元素的下标,加入到集合ArrayList
* 向mid的右边扫描,将所有满足 1000 的元素的下标,加入到集合ArrayList
* @return
*/
public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int findVal) {
if (left > right) {
return new ArrayList<Integer>();
}
int mid = (left + right) / 2;
int midVal = arr[mid];
if (midVal > findVal) {
return binarySearch2(arr, left, mid - 1, findVal);
} else if (midVal < findVal) {
return binarySearch2(arr, mid + 1, right, findVal);
} else {
ArrayList<Integer> arrayList = new ArrayList<>();
//向左
int temp = mid - 1;
while (true) {
if (temp < 0 || arr[temp] != findVal) {
break;
}
arrayList.add(temp);
temp -= 1;
}
//中间
arrayList.add(mid);
//右边
temp = mid + 1;
while (true) {
if (temp > arr.length-1 || arr[temp] != findVal) {
break;
}
arrayList.add(temp);
temp += 1;
}
return arrayList;
}
}
}
插值查找
public class InsertValueSearch {
public static void main(String[] args) {
int[] arr = new int[100];
for (int i = 0; i <= 99; i++) {
arr[i] = i + 1;
}
int i = insertValueSearch(arr, 0, 99, 5);
System.out.println(i);
}
/**
* 重复的值不能全部找到
*
* @param arr
* @param left 左边的索引
* @param right 右边的索引
* @param findVal 要寻找的值
* @return 没有找到返回-1
*/
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;
}
int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
int midVal = arr[mid];
if(midVal < findVal){
return insertValueSearch(arr,mid+1,right,findVal);
}else if(midVal > findVal){
return insertValueSearch(arr,left,mid-1,findVal);
}else{
return mid;
}
}
}
斐波那契查找算法
public class FibonacciSearch {
public static int maxSize = 20;
public static void main(String[] args) {
int[] arr = {1, 8, 10, 89, 1000, 1234};
System.out.println(fibSearch(arr, 89));
}
//因为后面 mid=low+F(k-1)-1,需要使用到斐波那契数列,所以我们要先获取
//用非递归的方法得到一个斐波那契数列
public static int[] fib() {
int[] f = new int[maxSize];
f[0] = 1;
f[1] = 1;
for (int i = 2; i < maxSize; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f;
}
/**
* 使用非递归的方式
*
* @param a 数组
* @param key 在a中要查找的值
* @return 返回对应的下标,找不到返回-1
*/
//mid=low+F(k-1)-1
public static int fibSearch(int[] a, int key) {
int low = 0;
int high = a.length - 1;
int k = 0;//表示斐波那契分割数值的下标
int mid = 0;//存放mid值
int f[] = fib();//获取到斐波那契数列
//获取到斐波那契分割数值的下标
while (high > f[k] - 1) {
k++;
}
//因为f[k] 值可能大于a的长度,所以我们需要使用Arrays类,构造一个新的数组,并指向temp[]
int[] temp = Arrays.copyOf(a, f[k]);
//Arrays的copyOf()方法传回的数组是新的数组对象,改变传回数组中的元素值,不会影响原来的数组。
//copyOf()的第二个自变量指定要建立的新数组长度,如果新数组的长度超过原数组的长度,则保留数组默认值
//使用a数组最后的数填充 temp
//例:{1,8,10,1000,1234,0,0} =》 {1,8,10,1000,1234,1234,1234}
for (int i = high + 1; i < temp.length; i++) {
temp[i] = a[high];
}
//使用while来循环处理,找到我们的数key
while (low <= high) {
mid = low + f[k - 1] - 1;
if (key < temp[mid]) {//我们应该继续向数组的前面查找(左边)
high = mid - 1;
//为什么 k--
//全部元素 = 前面的元素 + 后边元素
//f[k] = f[k-1] + f[k-2]
//因为前面有f[k-1]个元素,所以可以继续拆分f[k-1] = f[k-2] + f[k-3]
//即在f[k-1] 的前面继续查找k--
//即下次循环 mid=f[k-1-1]-1
k--;
} else if (key > temp[mid]) {//继续向数组的后边查找
low = mid + 1;
//为什么是k-=2?
//全部元素 = 前面的元素 + 后边元素
//f[k] = f[k-1] + f[k-2]
//因为后面有f[k-2]个元素,所以可以继续拆分f[k-1] = f[k-3] + f[k-4]
//即在f[k-2] 的后面继续查找k-=2
//即下次循环 mid=f[k-1-2]-1
k -= 2;
} else {//找到
//需要确定,返回的是哪个下标
if (mid <= high) {
return mid;
} else {
return high;
}
}
}
return -1;
}
}