二分查找、部分有序二分查找

二分查找的执行过程

1.从已经排好序的数组或区间中,取出中间位置的元素,将其与我们的目标值进行比较,判断是否相等,如果相等

则返回。

2.如果 nums[mid] 和 target 不相等,则对 nums[mid] 和 target 值进行比较大小,通过比较结果决定是从 mid

的左半部分还是右半部分继续搜索。如果 target > nums[mid] 则右半区间继续进行搜索,即 left = mid + 1; 若

target < nums[mid] 则在左半区间继续进行搜索,即 right = mid -1;

二分查找模版

    int binary_search(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) {
                right = mid - 1;
            } else if (nums[mid] == target) {//相等就返回
                return mid;
            }
        }
        return -1;
    }

    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) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else if (nums[mid] == target) { // 别返回,锁定左侧边界
                right = mid - 1;
            }
        }
        // 最后要检查 left 越界的情况
        if (left >= nums.length || nums[left] != target) {
            return -1;
        }
        return left;//左侧边界返回left
    }

    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) {
                right = mid - 1;
            } else if (nums[mid] == target) { // 别返回,锁定右侧边界
                left = mid + 1;
            }
        }
        // 最后要检查 right 越界的情况
        if (right >= nums.length || nums[right] != target) {
            return -1;
        }
        return right;//求右侧边界返回right
    }

代码

    public int search(int[] nums, int target) {
        if (nums == null || nums.length == 0){
            return -1;          
        }
        int left = 0;
        int 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{
                return mid;
            }

        }
        return -1;

    }

在排序数组中查找元素的第一个和最后一个位置

https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/da-jia-bu-yao-kan-labuladong-de-jie-fa-fei-chang-2/

我写的题解,很好懂

https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/di-gui-er-fen-cha-zhao-dai-ma-jian-ji-ch-c9d4/

    List<Integer> list = new ArrayList<>();

    public  void fun(int[] nums, int target, int left, int right) {
        if (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                list.add(mid);
                fun(nums, target, left, mid - 1);
                fun(nums, target, mid + 1, right);
            } else if (nums[mid] > target) {
                fun(nums, target, left, mid - 1);
            } else {
                fun(nums, target, mid + 1, right);
            }
        }

    }

    public  int[] searchRange(int[] nums, int target) {
        if (nums.length == 0) {
            return new int[]{-1, -1};
        }
        fun(nums, target, 0, nums.length - 1);
        if (list.size() == 0) {
            return new int[]{-1, -1};
        }
        return new int[]{Collections.min(list), Collections.max(list)};

    }

剑指 Offer 53 - I. 在排序数组中查找数字 I (递归二分查找)

https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/solution/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-idi-gui-er/

部分有序二分查找

题解

https://mp.weixin.qq.com/s/33aOwDGFQ5omE3sHmVLXVA

33. 搜索旋转排序数组

public static int search(int[] nums, int target) {
        int start = 0;
        int end = nums.length - 1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] == target) {
                return mid;
            }
            //数组从中间分开成左右两部分的时候,一定有一部分的数组是有序的;
            //启示我们可以在常规二分查找的时候查看当前 mid 为分割位置分割出来的两个部分 [l, mid] 和 [mid + 1, r] 哪个部分是有序的,
            //并根据有序的那个部分确定我们该如何改变二分查找的上下界,因为我们能够根据有序的那部分判断出 target 在不在这个部分
            //情况A:旋转点在中位数右侧,那么中位数左侧是个升序区
            if (nums[mid] >= nums[start]) {
                if (target >= nums[start] && target < nums[mid]) {
                    end = mid - 1;
                } else {
                    start = mid + 1;
                }
            } else {//在中位数右侧有一个升序区
                if (target > nums[mid] && target <= nums[end]) {
                    start = mid + 1;
                } else {
                    end = mid - 1;
                }
            }
        }
        return -1;
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值