大家好,我是听雨,是一名跨考计算机专业的研一学生。为提高编程的水平,计划每天刷编程题目。由于我是算法小白,所以开始只能从简单题开始写贴,请大家多多包涵,希望和大家一起进步
今天的专题是二分查找,由于该算法比较简单,我就将三道题放在一起了,主要原理大同小异。大家简单看看就好。
题目
一. 二分查找
二. 第一个错误的版本
三. 搜索插入位置
解题思路
三道题的原理都是相同的,只需要设置
l
e
f
t
left
left和
r
i
g
h
t
right
right指针首先指向数组首尾,并令
m
i
d
mid
mid 指针 =
(
l
e
f
t
+
r
i
g
h
t
)
/
2
(left + right)/2
(left+right)/2。之后用
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid]与
t
a
r
g
e
t
target
target的值比较。由于数组是升序的,当
t
a
r
g
e
t
>
n
u
m
s
[
m
i
d
]
target > nums[mid]
target>nums[mid]则说明,该元素不可能在
m
i
d
mid
mid指针的左侧了,所以更新
l
e
f
t
=
m
i
d
+
1
,
m
i
d
=
(
l
e
f
t
+
r
i
g
h
t
)
/
2
left = mid + 1, mid = (left + right)/2
left=mid+1,mid=(left+right)/2,继续对比。同理
t
a
r
g
e
t
《
n
u
m
s
[
m
i
d
]
target 《 nums[mid]
target《nums[mid]则说明,该元素不可能在
m
i
d
mid
mid指针的右侧了,,所以更新
r
i
g
h
t
=
m
i
d
−
1
,
m
i
d
=
(
l
e
f
t
+
r
i
g
h
t
)
/
2
right= mid - 1, mid = (left + right)/2
right=mid−1,mid=(left+right)/2. 直到最后会出先两种情况,要么
n
u
m
s
[
m
i
d
]
=
t
a
r
g
e
t
nums[mid] = target
nums[mid]=target,则返回
m
i
d
mid
mid 即可。如果数组中不存在该值,最后的区间会缩小至一个点退出循环。此时
l
e
f
t
left
left的值就是将
t
a
r
g
e
t
target
target插入数组的下标值。
二分查找的时间复杂度为
O
(
l
o
g
n
)
O(logn)
O(logn)。以下是图解:
代码
第一题
class Solution {
public int search(int[] nums, int target) {
int left = 0,right = nums.length - 1;
int mid = (left + right) / 2;
while(left <= right){
if(target > nums[mid]){
left = mid + 1;
}else if(target < nums[mid]){
right = mid - 1;
}else{
return mid;
}
mid = (left + right) / 2;
}
return -1;
}
}
结果:
第二题
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left = 1, right = n;
while (left <= right) { // 循环直至区间左右端点相同
int mid = left + (right - left) / 2; // 防止计算时溢出
if (isBadVersion(mid)) {
right = mid - 1; // 答案在区间 [left, mid] 中
} else {
left = mid + 1; // 答案在区间 [mid+1, right] 中
}
}
// 此时有 left == right,区间缩为一个点,即为答案
return left;
}
}
结果
第三题
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0, right = nums.length - 1;
int mid = 0;
while(left <= right){
mid = (left + right) / 2;
if(nums[mid] == target){
return mid;
}
if(target > nums[mid]){
left = mid + 1;
}
if(target < nums[mid]){
right = mid - 1;
}
}
return left;
}
}
总结
二分法是搜索中一个比较基础且重要的方法,对于有序数组来说,它的效率很高,是一个程序员应当熟练掌握的。