前言:
打卡只是为了本人便于复盘,坚持;
二分查找以及其应用需要总结并且熟练掌握模板
题目一、278. 第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 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
方法一:二分查找(题目为二分查找的应用)
思路及算法:
因为题目要求尽量减少调用检查接口的次数,所以不能对每个版本都调用检查接口,而是应该将调用检查接口的次数降到最低,其实也就是缩小时间复杂度。
举个例子比如一组数据: 00000001111111 题目的意思就是找到第一个为1的位置下标,通过二分查找不断缩小下标所在区间最终找到改位置。
注意: 下标与产品版本号相差1,下标为n-1所对应的最后一个版本号是n。
注意: 跳出循环的时候是左右指针(注意不是版本号)相邻的时候。
代码:
/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */
public class Solution extends VersionControl {
public int firstBadVersion(int n)
{
int left = - 1 , right = n; //下标从1开始到n结束
//进行左右指针的调整
while(left < right -1 )
{
//该循环成立的条件注意是下标
//int mid = (left + right)/2;//这样可能会造成整型的溢出
int mid = ( right +left)>>>1; //普通的位运算
//注意版本号和下标相差为1
if(isBadVersion(mid+1))//注意该接口判断的是一个坏的版本号
right = mid;
else left = mid;
}
//表明左边是好的,右边是坏的
return right+1;
}
}
题目二、
35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 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
方法一:直接遍历查找
思路及算法:
直接遍历查找目标值如果给定的数组有该目标值则返回该目标值的下标,如果目标值比数组中的某一个数小就返回nums[i]的下标数,如果目标数比数组的最后一个数还大,就返回数组长度。
注意:自己的错误点是先用二分查找寻找数组中是否是否有该目标数,然后再讨论没有的情况,三种情况小于第一个数return0,大于最后一个数retutn length ,在中间return left +1。但是通过不了
代码:
class Solution {
public int searchInsert(int[] nums, int target) {
for (int i = 0; i <nums.length ; i++) {
if (nums[i]==target){
return i;
}else if (target<nums[i]){
return i;
}if(target>nums[nums.length-1]){
return nums.length;
}
}
return 0;
}
}