二分查找之查找数组中相同的多个元素详解
思路分析
- 如果数组中有多个相同的元素,而正好要查找这些元素的下标,则应该以集合的形式返回
- 二分查找的整体思路不变,还是使用递归查找,若没有找到则返回空集合
- 但是当找到一个要查找的元素时,不能直接返回,而是向左或者向右扫描,判断找到的这个元素左侧或者右侧元素也是要查找的值,如果是,则记录其索引,如果不是,则结束查找,直接返回
- 源码及详解见下
源码及分析
/**
* 二分查找,需要保证数组元素有序
* 二分查找扩展之查找该数组中相同的多个元素,以集合的形式返回
*
* @param arr 要查找的原数组
* @param left 左侧索引
* @param right 右侧索引
* @param findVal 要查找的值
* @return 以集合的形式返回要查找的值
*/
public static List<Integer> binarySearch2(int[] arr, int left, int right, int findVal) {
//如果数组查找完还没有找到,直接返回 空集合
if (left > right) {
return new ArrayList<>();
}
//定义变量保存中间值和中间索引
int mid = (left + right) / 2;
int midVal = arr[mid];
//如果要查找的值在中间值的右边,则向右递归
if (findVal > midVal) {
return binarySearch2(arr, mid + 1, right, findVal);
//如果要查找的值在中间值的左边,则向左递归
} else if (findVal < midVal) {
return binarySearch2(arr, left, mid - 1, findVal);
} else {
//否则找到要查找的值,向左和向右扫描,查找是否有相同的
//定义集合保存查找到的元素索引
List<Integer> list = new ArrayList<>();
//向左扫描
int index = mid - 1;
while (true) {
if (index < 0 || arr[index] != findVal) {
break;
}
list.add(index);
index--;
}
list.add(mid);
//向右扫描
index = mid + 1;
while (true) {
if (index == arr.length || arr[index] != findVal) {
break;
}
list.add(index);
index++;
}
return list;
}
}