【二分查找】LeetCode相关简单题目

本文详细介绍了二分查找算法在不同编程问题中的应用,如搜索插入位置、查找错误版本等。提供了递归和循环两种实现方式的模板,并分析了边界条件的处理,强调了在实际编程中避免错误的关键点。通过这些模板,读者可以更好地理解和应用二分查找算法。
摘要由CSDN通过智能技术生成

题目技巧

二分查找的思路不难理解,但是边界条件容易出错,比如 循环结束条件中 left 和 right 的关系,更新 left 和 right 位置时要不要加 1 减 1。

下面给出两个可以直接套用的模板,记住就好了,免除边界条件出错。

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length - 1; // 注意
        while(left <= right) { // 注意
            int mid = left + (right - left) / 2; // 注意
            if(nums[mid] == target) { // 注意
                // 相关逻辑
            } else if(nums[mid] < target) {
                left = mid + 1; // 注意
            } else {
                right = mid - 1; // 注意
            }
        }
        // 相关返回值
        return 0;
    }
}
class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length; // 注意
        while(left < right) { // 注意
            int mid = left + (right - left) / 2; // 注意
            if(nums[mid] == target) {
                // 相关逻辑
            } else if(nums[mid] < target) {
                left = mid + 1; // 注意
            } else {
                right = mid; // 注意
            }
        }
        // 相关返回值
        return 0;
    }
}

1.二分查找

题目:
:

思路:

这是一道典型的二分查找题目,
给定一个区间,每次找到区间中间的值与目标值进行比较,
如果匹配上了,直接返回。
如果中间值大于目标值,说明中间值右边的所有都大于目标值(有序),所以淘汰中间值及其右边的值。
反之亦然。
最终区间长度<=0就结束循环或者递归。

代码:

//递归方法
class Solution {
    public int search(int[] nums, int target) {
        return binarySearch(nums, 0, nums.length - 1, target);
    }
    public int binarySearch (int[]nums, int star, int end, int target) {
        if (star > end) {
            return -1;
        }
        int mid = (star + end) / 2;  //注意
        if (nums[mid] == target) {
            return mid;
        }
        else if (nums[mid] > target) {
            return binarySearch(nums, star, mid - 1, target);
        }
        else {
            return binarySearch(nums, mid + 1, end, target);
        }
    }
}

// 循环
class Solution {
  public int search(int[] nums, int target) {
    int pivot, left = 0, right = nums.length - 1;
    while (left <= right) {
      pivot = left + (right - left) / 2;
      if (nums[pivot] == target) return pivot;
      if (target < nums[pivot]) right = pivot - 1;
      else left = pivot + 1;
    }
    return -1;
  }
}

2.第一个错误版本

题目:
在这里插入图片描述
思路:

题目理解:当一个版本为正确版本,则该版本之前的所有版本均为正确版本;当一个版本为错误版本,则该版本之后的所有版本均为错误版本。我们可以利用这个性质进行二分查找。
注意:与上题有所不同,上题最快一次即可匹配成功,本题需要则总是logn次,
因为返回值必须满足:它本身是错误版本,它前面都是正确版本,后面都是错误版本。
解答:假设区间为star,end,mid为中间版本,
每次判断mid是什么版本,如果是坏版本,那么抛弃所有该版本右边的版本(不包括该版本),
反之,抛弃该版本以及所有左边的版本(包括该版本)
最终区间<=0返回答案star。

代码:

// 循环
public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        if (isBadVersion(1)) {
            return 1;
        }
        int star = 1, end = n, mid;
        while (star < end) {
            mid = star + (end - star) / 2; // 防止计算时溢出
            if (isBadVersion(mid) ) {
                end = mid;
            }
            else {
                star = mid + 1;
            }
        }
        return star;
    }
}

3.搜索插入位置

题目:
在这里插入图片描述
思路:

题目理解:在一个有序数组中找第一个大于等于 target 的下标。
该题与上两题类似,不断用二分法逼近目标值即可。

代码:

// 循环
class Solution {
    public int searchInsert(int[] nums, int target) {
        int star = 0, end = nums.length - 1, mid;
        while (star <= end) {
            mid = (end - star) / 2 + star;
            if (nums[mid] == target) {
                return mid;
            }
            else if (nums[mid] > target) {
                end = mid - 1;
            }
            else {
                star = mid + 1;
            }
        }
        return star;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值