二分查找

@Test
public void testBinSearch() {
    int[] i = {1, 3, 5, 6, 8};
    int[] r1 = {bS1(i, 0), bS1(i, 1), bS1(i, 3), bS1(i, 6), bS1(i, 8), bS1(i, 9)};
    System.out.println(Arrays.toString(r1));
    System.out.println("--------------------");
    int[] r2 = {bS2(i, 0), bS2(i, 1), bS2(i, 3), bS2(i, 6), bS2(i, 8), bS2(i, 9)};
    System.out.println(Arrays.toString(r2));
    System.out.println("--------------------");
    int[] r3 = {bS3(i, 0), bS3(i, 1), bS3(i, 3), bS3(i, 6), bS3(i, 8), bS3(i, 9)};
    System.out.println(Arrays.toString(r3));
    System.out.println("--------------------");
    int[] r4 = {bS4(i, 0), bS4(i, 1), bS4(i, 3), bS4(i, 6), bS4(i, 8), bS4(i, 9)};
    System.out.println(Arrays.toString(r4));
}

public int bS1(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    // 终止条件[right + 1, right],此时搜索区间为空
    while (left <= right) {
        int mid = left + ((right - left) >> 1);
        if (nums[mid] == target) return mid;
        if (nums[mid] < target) left = mid + 1;
        if (nums[mid] > target) right = mid - 1;
    }
    return -1;
}

public int bS2(int[] nums, int target) {
    int left = 0;
    int right = nums.length; // 右边界初始为length,取不到
    // 终止条件[right, right],此时搜索区间非空,但右边界不可能为target
    while (left < right) {
        int mid = left + ((right - left) >> 1);
        if (nums[mid] == target) return mid;
        if (nums[mid] < target) left = mid + 1;
        if (nums[mid] > target) right = mid; // right边界永远不可能为target,不需要对结果打补丁
    }
    return -1;
}

public int bS3(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1; // 右边界初始为最后一个元素
    // 终止条件[right, right],此时搜索区间非空,且右边界可能为target,需要对单独最后一个元素进行判断
    while (left < right) {
        int mid = left + ((right - left) >> 1);
        if (nums[mid] == target) return mid;
        if (nums[mid] < target) left = mid + 1;
        if (nums[mid] > target) right = mid - 1; // right边界有可能为target,需要对结果打补丁
    }
    return nums[left] == target ? left : -1;
}

public int bS4(int[] nums, int target) {
    int left = 0;
    int right = nums.length; // 右边界初始为length,有可能有边界从始至终都没有变化,需要单独处理
    // 终止条件[right, right],此时搜索区间非空,且右边界可能为target,需要对单独最后一个元素进行判断
    while (left < right) {
        int mid = left + ((right - left) >> 1);
        if (nums[mid] == target) return mid;
        if (nums[mid] < target) left = mid + 1;
        if (nums[mid] > target) right = mid - 1; // right边界有可能为target,需要对结果打补丁
    }
    if (right == nums.length) return -1;
    return nums[left] == target ? left : -1;
}

@Test
public void testBinSearchPlus() {
    int[] nums = {1, 2, 2, 2, 3};
    int[] r1 = {bSL(nums, 0), bSL(nums, 1), bSL(nums, 2), bSL(nums, 3), bSL(nums, 4)};
    System.out.println(Arrays.toString(r1));
    System.out.println("-----------------");
    int[] r2 = {bSR(nums, 0), bSR(nums, 1), bSR(nums, 2), bSR(nums, 3), bSR(nums, 4)};
    System.out.println(Arrays.toString(r2));
}

// 最左侧的target
public int bSL(int[] nums, int target) {
    int left = 0;
    int right = nums.length;
    while (left < right) { // 结束条件left == right
        int mid = left + ((right - left) >> 1);
        if (nums[mid] >= target) right = mid; // 右边界可能为target
        if (nums[mid] < target) left = mid + 1; // 左边界依次逼近右边界
    }
    if (left == nums.length) return -1;
    return nums[left] == target ? left : -1;
}

// 最右侧的target
public int bSR(int[] nums, int target) {
    int left = 0;
    int right = nums.length;
    while (left < right) {
        int mid = left + ((right - left) >> 1);
        if (nums[mid] <= target) left = mid + 1; // 左边界的左侧可能为target
        if (nums[mid] > target) right = mid;
    }
    if (left == 0) return -1;
    return nums[left - 1] == target ? left - 1 : -1;
}

  

posted @ 2021-10-30 09:42  oumae  阅读(18)  评论(0编辑  收藏  举报