【Leetcode刷题】算法入门__二分查找例题

202 阅读3分钟

接上一篇笔记:

【Leetcode刷题】:算法入门__二分查找

这一章,我们看二分查找的两道例题


例题1:


这里是【Leetcode】原题出处,点击即可前往


1.1.题目要求:

  • 你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的

  • 假设你有 n 个版本 [1, 2, ..., n]你想找出导致之后所有版本出错的第一个错误的版本

  • 你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version

  • 是否在单元测试中出错。实现一个函数==来查找第一个错误的版本==。你应该尽量减少对调用 API 的次数。

示例 1:

输入:n = 5, bad = 4

输出:4

解释:

调用 isBadVersion(3) -> false

调用 isBadVersion(5) -> true

调用 isBadVersion(4) -> true

所以,4 是第一个错误的版本。

示例 2:

输入:n = 1, bad = 1

输出:1

提示:

1 <= bad <= n <= 231 - 1


1.2.解题思路:

  • 这道题的题意有些难懂,刚看到时我还不知道在说啥

  • 但细看后就知道,题目是让我们在众多版本中找到第一个错误的版本是哪一个

  • 类似在一个表[+++++*****]里找到第一个*

  • 而题目让我们找到第一个bad的状态

  • 这道题符合二分查找的条件

  • 我们每次都取到中间值middle然后判断版本错误。即isBadVersion(middle)

  • ==如果是错误版本,那么错误的版本之后必然全是错误的,反之,正确的版本之前全是正确的==

  • 根据这一点,我们来更新区间。

  • 在循环的最后,区间就缩为一个点,返回first即可

1.3.代码实现:

// The API isBadVersion is defined for you.
// bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
		long middle,first=1,end = n;
        while(first <= end){
        	
            middle = first + (end - first) / 2;
            
            if(isBadVersion(middle))
            	end = middle - 1;
                
            else
				first = middle + 1;
        }
        return first;
    }
};

例题2:


这里是【Leetcode】原题出处,点击即可前往


2.1.题目要求:

给定一个排序数组和一个目标值在数组中找到目标值,并返回其索引

如果目标值不存在于数组中返回==它将会被按顺序插入的位置==。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

  • 输入: nums = [1,3,5,6]target = 5
  • 输出: 2

示例 2:

  • 输入: nums = [1,3,5,6], target = 2
  • 输出: 1

示例 3:

  • 输入: nums = [1,3,5,6], target = 7
  • 输出: 4

示例 4:

  • 输入: nums = [1,3,5,6], target = 0
  • 输出: 0

示例 5:

  • 输入: nums = [1], target = 0
  • 输出: 0

提示:

- 1 <= nums.length <= 104

  • -104 <= nums[i] <= 104

  • nums 为无重复元素的升序排列数组

  • -104 <= target <= 104

2.2.解题思路:

  • 在一个数组里查找一个整数,而且是==有序,无重复元素且有范围的数组==,很显然可以使用==二分查找==来解决问题

  • 这道题其实和上一道差不多,只不过多了一个要求,就是==如果数组里没有目标值,那么求出目标值应插入的位置== opt

  • 如果在循环中没能找到target相应的位置,那么其位置应该在数组的末尾

2.3.代码实现:

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int first = 0;
        int end = nums.size() - 1;	//定义target在左闭右闭的区间里,[left, right]
        while (first <= end) { 
            int middle = first + ((end - first) / 2);
            
            if (target < nums[middle]) {
                end = middle - 1; 	// target在左区间,更新区间为[first, middle-1]
            }
            else if (nums[middle] < target) {
                first = middle + 1; // target在右区间,更新区间为[middle + 1, end]
            }
            else { 
                return middle;	//target == nums[middle]
            }
        }
        return end + 1;	//将target插在数组末尾 
    }
};

好了,二分查找就看到这,下一篇我们看双指针!