二分法
题目一
- 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
解题思路
简单二分法直接解,注意存在int可能溢出的情况
class Solution {
public int search(int[] nums, int target) {
int min = 0;
int max = nums.length - 1;
while(min <= max){
int mid = min + (max-min)/2;
if(nums[mid] > target){
max = mid - 1;
}else if(nums[mid] < target){
min = mid + 1;
}else{
return mid;
}
}
return -1;
}
}
题目二
- 第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
解题思路
其实就是二分法,我们不妨将图画出来
我们只要从中间开始查找,判断中间是否为true即可,如果是true,则将我们最早的时间记为mid,如果不是,则将开头=mid+1,重新赋值mid,循环多次,最后输出left即可
/* 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 start=1, end=n;
while(start<end)
{
int middle=start+(end-start)/2;//找到n个版本的中间的一个版本
if(isBadVersion(middle))//判断中间版本是否是错误版本,若是,则缩小第一个错误版本的出现范围为[1,middle]
{
end=middle;
}
else //否则缩小第一个错误版本出现范围为[middle+1,n]
{
start=middle+1;
}
}
return start;//当start==end时则循环结束,此时start==end等于第一个错误版本
}
}
题目三
- 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
解题思路
说白了就是找数组内的下标,通常我们第一个想到的应该是二分法,和上面的方法一样,带入即可解,不过要注意,这个返回下标值最小值,也就是返回min。
class Solution {
public int searchInsert(int[] nums, int target) {
int min=0;
int max=nums.length-1;
int mid=0;
while(min<=max)
{
mid=min+(max-min)/2;
if(nums[mid]>target)
{
max=mid-1;
}
else if(nums[mid]<target)
{
min=mid+1;
}
else
return mid;
}
return min;
}
}```