二分查找超级好的模板-清晰

参考博客   chttps://segmentfault.com/a/1190000016825704

  1. 标准的二分查找
  2. 二分查找左边界
  3. 二分查找右边界

/**
 * desc: 记住条件有> < mid 的都是要 +1 因为mid已经不符合条件
 *
 * @author junlin
 * @since 2021/11/23
 **/
public class erfen模板 {
    /*
     标准二分查找
     */
    public static int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (nums[mid] == target) return mid;
            else if (nums[mid] > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }

    /*
    二分查找左边界  -  查找第一个大于等于target的元素 注意必须等于target否则找不到,也可以返回索引就行
    记住查找左边界 nums[mid] < target 因为如果比target小,只能移动+1,而不是原地
    1.数组有序,但包含重复元素
    2.数组部分有序,且不包含重复元素
    3.这个是从小到大排好序的数组,如果是从大到小,则 if else条件相反
     */
    public static int searchLeft(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return nums[left] == target ? left : -1;
    }

    /*
    二分查找左边界
    3.数组部分有序,且包含重复元素
     */
    public static int searchLeft2(int[] nums, int target) {
        int left = 0;
        int 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) {
                right = mid;
            } else {
                right--;
            }
        }
        return nums[left] == target ? left : -1;
    }

    /*
    二分查找右边界有序
    记住查找右边界 nums[mid] > target 因为如果比target大,只能移动-1,而不是原地
    1.有序
    2.部分有序 且不含重复元素
     */
    public static int searchRight(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            // 注意后面要加1  对于奇数还是偶数,这个中间的位置都是偏右的
            int mid = left + ((right - left) >> 1) + 1;
            if (nums[mid] > target) {
                right = mid - 1;
            } else {
                left = mid;
            }
        }
        return nums[right] == target ? right : -1;
    }

    public static int testLeft() {
        int[] nums = new int[]{1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 6, 6};
        int target = 3;
        return searchLeft(nums, target);
    }

    // 测试方法
    public static int testRight() {
        int[] nums = new int[]{1, 1, 1, 1, 1, 1, 2, 2, 4};
        int target = 1;
        return searchRight(nums, target);
    }

    public static void main(String[] args) {
        System.out.println(testLeft());
        System.out.println(testRight());
        System.out.println(testSearchFirstBig());
    }

    /*
    查找第一个大于target的元素
    利用右边界模板:查找最后一个大于等于target的元素   最后默认索引是最后一个 比target小的元素,或者等于target的元素
    索引加+1就是第一个 大于target的元素
     */
    public static int searchFirstBig(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            // 注意后面要加1  对于奇数还是偶数,这个中间的位置都是偏右的
            int mid = left + ((right - left) >> 1) + 1;
            if (nums[mid] > target) {
                right = mid - 1;
            } else {
                left = mid;
            }
        }
        return right;
    }

    // 测试方法
    public static int testSearchFirstBig() {
        int[] nums = new int[]{1, 1, 21, 22,222};
        int target = 23;
        return searchFirstBig(nums, target);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值