1. 查找思路
1.1 二分查找(递归实现,只返回第一个找到位置的下标)
- 基本条件:left > right,说明没找到,返回-1
- 得到中间点下标 mid
- 比较,分割,查找
3.1 若 待寻找的数 < 中间点数值:继续在中间点左边数组中查找
3.2 若 待寻找的数 > 中间点数值:继续在中间点右边数组中查找
3.3 若 待寻找的数 = 中间点数值:找到,返回当前中间点下标
1.2 二分查找(递归实现,返回全部找到位置的下标)
- 新建list,存放要返回的全部下标值
- 基本条件:left > right,说明没找到,返回-1
- 得到中间点下标 mid
- 比较,分割,查找
3.1 若 待寻找的数 < 中间点数值:继续在中间点左边数组中查找
3.2 若 待寻找的数 > 中间点数值:继续在中间点右边数组中查找
3.3 若 待寻找的数 = 中间点数值:找到,分别逐个查看找到位置左边和右边是否有相同值,将所有临近相同值的下标按顺序放入list:- 向左遍历,寻找相同值并按从小到大顺序加入list
- 添加mid到list
- 向右遍历,寻找相同值并按从小到大顺序加入list
- 返回找到位置的全部下标list
2. 代码实现
2.1 递归实现
/**
* 二分查找(递归实现,只返回第一个找到位置的下标)
* 二分法递归查找array里是否有searchValue,有则返回第一个发现点的下标,没有则返回-1
* 思路:
* 1. 基本条件:left > right,说明没找到,返回-1
* 2. 得到中间点下标 mid
* 3. 比较,分割,查找
* 3.1 若 待寻找的数 < 中间点数值:继续在中间点左边数组中查找
* 3.2 若 待寻找的数 > 中间点数值:继续在中间点右边数组中查找
* 3.3 若 待寻找的数 = 中间点数值:找到,返回当前中间点下标
* @param array - 要查找的数组
* @param searchValue - 要查找的数值
* @param left - 二分时左指针
* @param right - 二分时右指针
* @return - 找到返回第一个数值所在下标,没找到返回-1
*/
public static int binarySearchByRecursion(int[] array, int searchValue, int left, int right) {
// 1. 基本条件:left > right,说明没找到,返回-1
if (left > right) {
return -1;
}
// 2. 得到中间点下标 mid
int mid = (left + right) / 2;
// 3. 比较,分割,查找
// 3.1 若 待寻找的数 < 中间点数值:继续在中间点左边数组中查找
if (searchValue < array[mid]) {
return binarySearchByRecursion(array, searchValue, left, mid - 1);
}
// 3.2 若 待寻找的数 > 中间点数值:继续在中间点右边数组中查找
else if (searchValue > array[mid]) {
return binarySearchByRecursion(array, searchValue, mid + 1, right);
}
// 3.3 若 待寻找的数 = 中间点数值:找到,返回当前中间点下标
else {
return mid;
}
}
/**
* 二分查找(递归实现,返回全部找到位置的下标)
* 二分法递归查找array里是否有searchValue,有则返回所有满足的点的下标,没有则返回空list
* 思路:
* 0. 新建list,存放要返回的全部下标值
* 1. 基本条件:left > right,说明没找到,返回-1
* 2. 得到中间点下标 mid
* 3. 比较,分割,查找
* 3.1 若 待寻找的数 < 中间点数值:继续在中间点左边数组中查找
* 3.2 若 待寻找的数 > 中间点数值:继续在中间点右边数组中查找
* 3.3 若 待寻找的数 = 中间点数值:找到,分别逐个查看找到位置左边和右边是否有相同值,将所有临近相同值的下标按顺序放入list
* (1) 向左遍历,寻找相同值并按从小到大顺序加入list
* (2) 添加mid到list
* (3) 向右遍历,寻找相同值并按从小到大顺序加入list
* (4) 返回找到位置的全部下标list
* @param array - 要查找的数组
* @param searchValue - 要查找的数值
* @param left - 二分时左指针
* @param right - 二分时右指针
* @return - 返回所有满足的点的下标,没有则返回空list
*/
public static ArrayList<Integer> binarySearchForAllByRecursion(int[] array, int searchValue, int left, int right) {
// 0. 新建list,存放要返回的全部下标值
ArrayList<Integer> searchValueIndexList = new ArrayList<>();
// 1. 基本条件:left > right,说明没找到,返回-1
if (left > right) {
return searchValueIndexList;
}
// 2. 得到中间点下标 mid
int mid = (left + right) / 2;
// 3. 比较,分割,查找
// 3.1 若 待寻找的数 < 中间点数值:继续在中间点左边数组中查找
if (searchValue < array[mid]) {
return binarySearchForAllByRecursion(array, searchValue, left, mid - 1);
}
// 3.2 若 待寻找的数 > 中间点数值:继续在中间点右边数组中查找
else if (searchValue > array[mid]) {
return binarySearchForAllByRecursion(array, searchValue, mid + 1, right);
}
// 3.3 若 待寻找的数 = 中间点数值:找到,分别逐个查看找到位置左边和右边是否有相同值,将所有临近相同值的下标按顺序放入list
else {
// (1) 向左遍历,寻找相同值并按从小到大顺序加入list
int index = mid - 1;
Stack<Integer> leftIndexStack = new Stack<>();
while (index >= 0 && searchValue == array[index]) {
leftIndexStack.push(index);
index--;
}
while (!leftIndexStack.isEmpty()){
searchValueIndexList.add(leftIndexStack.pop());
}
// (2) 添加mid到list
searchValueIndexList.add(mid);
// (3) 向右遍历,寻找相同值并按从小到大顺序加入list
index = mid + 1;
while (index <= array.length - 1 && searchValue == array[index]) {
searchValueIndexList.add(index);
index++;
}
// (4) 返回找到位置的全部下标list
return searchValueIndexList;
}
}
2.2 循环实现
/**
* 二分查找(loop实现,只返回第一个找到位置的下标)
* 二分法循环查找array里是否有searchValue,有则返回第一个发现点的下标,没有则返回-1
* @param array - 要查找的数组
* @param searchValue - 要查找的数值
* @return - 找到返回第一个数值所在下标,没找到返回-1
*/
public static int binarySearchByLoop(int[] array, int searchValue) {
int left = 0;
int right = array.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (searchValue < array[mid]) {
right = mid - 1;
} else if (searchValue > array[mid]) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
}
/**
* 二分查找(递归实现,返回全部找到位置的下标)
* 二分法循环查找array里是否有searchValue,有则返回所有满足的点的下标,没有则返回空list
* @param array - 要查找的数组
* @param searchValue - 要查找的数值
* @return - 返回所有满足的点的下标,没有则返回空list
*/
public static ArrayList<Integer> binarySearchForAllByLoop(int[] array, int searchValue) {
ArrayList<Integer> searchValueIndexList = new ArrayList<>();
int left = 0;
int right = array.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (searchValue < array[mid]) {
right = mid - 1;
} else if (searchValue > array[mid]) {
left = mid + 1;
} else {
// 向左遍历
int index = mid - 1;
Stack<Integer> leftIndexStack = new Stack<>();
while (index >= 0 && searchValue == array[index]) {
leftIndexStack.push(index);
index--;
}
while (!leftIndexStack.isEmpty()) {
searchValueIndexList.add(leftIndexStack.pop());
}
// 添加mid
searchValueIndexList.add(mid);
// 向右遍历
index = mid + 1;
while (index <= array.length - 1 && searchValue == array[index]) {
searchValueIndexList.add(index);
index++;
}
return searchValueIndexList;
}
}
return searchValueIndexList;
}