百度百科
https://baike.baidu.com/item/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/10628618?fr=aladdin
思路
代码:
package com.search;
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
int binarySearch = binarySearch(arr, 0, arr.length-1, 7);
System.out.println(binarySearch);
}
public static int binarySearch(int [] arr,int left,int right,int findNum){
// 如果找不到返回-1,否则会死递归
if (left > right) {
return -1;
}
int mid = (left + right) / 2;
int midValue = arr[mid];
if (findNum > midValue) { //向右递归
return binarySearch(arr, mid + 1, right, findNum);
} else if (findNum <midValue) {
return binarySearch(arr, left, mid - 1, findNum);
} else {
return mid;
}
}
}
测试:
上面的代码只能找一个索引,倘若有多个值呢?比如{1,2,3,4,5,6,6,6};
优化后代码如下:
package com.search;
import java.util.ArrayList;
import java.util.List;
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1,2,3,3,3,4,5,6,6,6};
List<Integer> binarySearch2 = binarySearch2(arr, 0, arr.length-1, 6);
System.out.println(binarySearch2);
}
public static int binarySearch(int [] arr,int left,int right,int findNum){
// 如果找不到返回-1,否则会死递归
if (left > right) {
return -1;
}
int mid = (left + right) / 2;
int midValue = arr[mid];
if (findNum > midValue) { //向右递归
return binarySearch(arr, mid + 1, right, findNum);
} else if (findNum <midValue) {
return binarySearch(arr, left, mid - 1, findNum);
} else {
return mid;
}
}
public static List<Integer> binarySearch2(int [] arr,int left,int right,int findNum){
// 如果找不到返回-1,否则会死递归
if (left > right) {
return new ArrayList<>();
}
int mid = (left + right) / 2;
int midValue = arr[mid];
if (findNum > midValue) { //向右递归
return binarySearch2(arr, mid + 1, right, findNum);
} else if (findNum <midValue) {
return binarySearch2(arr, left, mid - 1, findNum);
} else { // 主要这里的修改,找到索引号好不要直接返回
//不要返回,继续分别从两边继续找
List<Integer> res = new ArrayList<>();
// 不要忘了第一次找到的索引
res.add(mid);
//从左边找
int temp = mid - 1;
while (true) {
if(temp < 0 || arr[temp] != findNum) {
break;
}
res.add(temp);
temp--;
}
// 右边找
temp = mid + 1;
while (true) {
if(temp> arr.length-1 || arr[temp] != findNum) {
break;
}
res.add(temp);
temp++;
}
return res;
}
}
}
测试结果:
插值查找算法
代码:
package com.search;
import java.util.ArrayList;
import java.util.List;
public class InsertValueSearch {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
int insertValueSearch = InsertValueSearch.insertValueSearch(arr, 0, arr.length - 1, 1);
System.out.println(insertValueSearch);
}
public static int insertValueSearch(int [] arr,int left,int right,int findNum){
System.out.println("查找次数");
// 如果找不到返回-1,否则会死递归
if (left > right
|| findNum < arr[0] || findNum > arr[arr.length - 1]) { // 这两个必须加上,否则mid可能因为findNum太大或者太小而越界!!!
return -1;
}
// 主要改这里,自适应
int mid = left + (right - left)*(findNum-arr[left])/(arr[right]-arr[left]);
int midValue = arr[mid];
if (findNum > midValue) { //向右递归
return insertValueSearch(arr, mid + 1, right, findNum);
} else if (findNum <midValue) {
return insertValueSearch(arr, left, mid - 1, findNum);
} else {
return mid;
}
}
}
对比结果:
int[] arr = {1,2,3,4,5,6,7,8,9,10};
如果用插值查找算法找1和10,一次便可找到,二分查找就要三次。