数据结构-二分查找

562 阅读1分钟

二分查找

通过不断缩小范围,比较min值,直到剩一个元素或者查找成功算法结束。

算法思路

  1. 获取数组array的左右边界left、right。
  2. min = (right+left)>>>1
  3. 比较array[min]与target的大小,确定区间
  4. 缩小区间
  5. 重复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. 当为正数时,找到了该值
  2. 负数时,此时它的值+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);
    }
}

结果

图片.png