leetcode -二分查找
704 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target,
写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int l = 0;
int r = nums.length - 1;
while(l <= r) {
int mid = (l + r) >> 1;//考虑溢出的问题,可以写成 l + (r - l) / 2
if (nums[mid] == target) {
return mid;
}
else if (nums[mid] > target) {
r = mid - 1;
}
else {
l = mid + 1;
}
}
return - 1;
}
- 第一个错误的版本
有 n 个版本 [1, 2, ..., n],找出导致之后所有版本出错的第一个错误的版本。
可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。
尽量减少对调用 API 的次数。
public int firstBadVersion(int n) {
int l = 1;
int r = n;
while(l < r) {
int mid = l + (r - l) / 2;
if (isBadVersion(mid)){
r = mid;
}
else {
l = mid + 1;
}
}
return l;
}
- 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。
如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int l = 0;
int r = nums.length - 1;
while(l <= r) {
int mid = (l + r) >> 1;
if (nums[mid] == target) {
return mid;
}
else if (nums[mid] > target) {
r = mid - 1;
}
else {
l = mid + 1;
}
}
return - 1;
}
关于二分的思想,其实就是依据性质将数据一分为二,一半满足,一半不满足
主要是细节方面的,可以看一下下面的文章
下面这两个模版是我看y神的笔记,就是关于二分是否要加1,r = mid的时候,就不需要加1,当 l = mid的时候就要加1,
如果一开始不怎么理解二分的细节问题,可以先照着模版写,多写几次,一边写,一边思考,或者在纸上面演示一遍。
public int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid; // check()判断mid是否满足性质
else l = mid + 1;
}
return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
public int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}