二分查找
通过不断缩小范围,比较min值,直到剩一个元素或者查找成功算法结束。
算法思路
- 获取数组array的左右边界left、right。
- min = (right+left)>>>1
- 比较array[min]与target的大小,确定区间
- 缩小区间
- 重复2-4直到找到或者区间内没有元素。
前提条件
数组必须是有序数组。
java实现
public static int binarySearchBasic(int[] arr,int target){
int left = 0;
int right= arr.length-1;
if (left<=right){
//无符号右移,相当于除2
int min = (left+right)>>>1;
if (target<arr[min]){
right = min-1;
}else if(arr[min]<target){
left=min+1;
}else {
return min;
}
}
// 如果找不到时,可以标记(其+1)的绝对值在查找数组中插入的位置。
return -(left+1);
}
(left+right)>>>1; 因为当Int取到最大值时+1会得到一个负数。将符号位也算上时可以解决该问题。
变式:通过二分查找向有序数组中插入新的元素
binarySearchBasic方法的返回值:-(left+1)
- 当为正数时,找到了该值
- 负数时,此时它的值+1的绝对值为该元素插入到数组中的位置。
注意:-(left+1)->+1取反是为了防止出现(当插入值比数组中所有元素都小时,返回值为0。此时算法的结果是找到了下标0的位置,与期待值不同。)的情况出现。
java实现
public static int[] insertTargetInArray(int[] array,int target){
//1. 通过二分查找找出其所在位置
int insertIndex= Arrays.binarySearch(array,target);
if (insertIndex<0){
//说明不在数组中,+1是为了找到要插入的位置
insertIndex = Math.abs(insertIndex+1);
}
// 2. 创建一个新的数组
int[] tempArray = new int[array.length+1];
// 3.复制array中insertIndex+1前的数据到tempArray中
System.arraycopy(array,0,tempArray,0,insertIndex);
tempArray[insertIndex] =target;
// 参数-> 被复制的数组,复制的起始位置,目标数组,复制的起始位置,复制的长度(个数)
System.arraycopy(array,insertIndex,tempArray,insertIndex+1,array.length-insertIndex);
return tempArray;
}
测试
public static void main(String[] args) {
int[] arr = {2,4,5};
Arrays.stream(insertTargetInArray(arr, 3)).forEach(System.out::println);
}
}