【读书笔记:算法小抄】二分搜索算法——Java版实现

普通版

package com.company;
import static java.lang.System.out;
import java.util.*;

public class Main {

    /* 二分搜索常见场景剖析 */
    // 1. 寻找一个数(基本的二分搜索),搜索区间为[left, right]
    public static int binarySearch(int[] nums, int target){
        int left = 0;
        int right = nums.length - 1;

        while(left <= right){ // 此处带等号原因是left==right的时候,这个元素也要检查
            int mid = left + (right - left) / 2; // 这样写可以防止溢出
            if(nums[mid] == target)
                return mid;
            else if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid - 1;
        }
        return -1;
    }

    // 2. 寻找左侧边界的二分搜索,搜索区间为[left, right)
    public static int left_bound(int[] nums, int target){
        if (nums.length == 0) return -1;
        int left = 0;
        int right = nums.length;

        while (left < right){  // 循环终止条件为left == right,此时超出了搜索区间[left, right)
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                right = mid;
            } else if (nums[mid] < target){
                left = mid + 1;
            } else if (nums[mid] > target){
                right = mid;
            }
        }

        if (left == nums.length) return -1;
        return nums[left] == target ? left : -1;
    }

    // 3. 寻找右侧边界的二分搜索,搜索区间为(left, right]
    public static int right_bound(int[] nums, int target){
        if (nums.length == 0) return -1;
        int left = 0;
        int right = nums.length;

        while (left < right){
            int mid = left + (right - left) / 2;
            if (nums[mid] == target)
                left = mid + 1;
            else if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid;
        }

        if (left == 0) return -1;
        return nums[left - 1] == target ? (left - 1) : -1;
    }

    public static void main(String[] args) {
    }

}

统一版(易于记忆)

package com.company;
import static java.lang.System.out;
import java.util.*;

public class Main {

    /* 二分搜索常见场景剖析 */
    // 1. 寻找一个数(基本的二分搜索),搜索区间为[left, right]
    public static int binarySearch(int[] nums, int target){
        int left = 0;
        int right = nums.length - 1;

        while(left <= right){ // 此处带等号原因是left==right的时候,这个元素也要检查
            int mid = left + (right - left) / 2; // 这样写可以防止溢出
            if(nums[mid] == target)
                return mid;
            else if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid - 1;
        }
        return -1;
    }

    // 2. 寻找左侧边界的二分搜索,搜索区间为[left, right)
    public static int left_bound(int[] nums, int target){
        int left = 0, right = nums.length - 1;

        while (left <= right){
            int mid = left + (right - left) / 2;

            if (nums[mid] == target){ // 收缩右侧边界
                right = mid - 1;
            } else if (nums[mid] < target){
                left = mid + 1;
            } else if (nums[mid] > target){
                right = mid - 1;
            }
        }

        // 检测left越界的情况
        if (left > nums.length - 1 || nums[left] != target)
            return -1;
        return left;  // 或者返回right + 1也可以
    }

    // 3. 寻找右侧边界的二分搜索,搜索区间为(left, right]
    public static int right_bound(int[] nums, int target){
        int left = 0, right = nums.length - 1;

        while (left <= right){
            int mid = left + (right - left) / 2;
            if (nums[mid] == target)
                left = mid + 1; // 收缩左侧边界,向右侧靠拢
            else if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid - 1;
        }

        // 检查right越界情况
        if (right < 0 || nums[right] != target)
            return -1;
        return right;
    }

    public static void main(String[] args) {
        int[] nums = {1, 3, 3, 3, 4};
        int target = 3;

        // 1. 基本二分搜索
        out.println(binarySearch(nums, target));  // 2

        // 2. 左侧边界二分搜索
        out.println(left_bound(nums, target));  // 1

        // 3. 右侧边界二分搜索
        out.println(right_bound(nums, target));  // 3
    }

}


如果你认为对你有用,关注我的微信公众号支持我一下吧!~

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值