【LeetCode & 剑指offer刷题】查找与排序题1:二分查找小结
【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)
二分查找小结
/* 类型1
功能:查找和目标值完全相等的数
返回:如果存在,返回对应位置索引,否则返回-1
例:
[2, 4, 5, 6, 9]
,
target = 6
,返回索引
3
*/
int
find
(
vector
<
int
>&
a
,
int
target
)
{
int
left
=
0
,
right
= a.size
();
//
与
stl
中喜欢把
end
指向末尾后一个元素的做法类似
while
(left < right)
{
int
mid
=
left
+
(
right
-
left
)
/
2
;
if
(
a
[
mid
]
<
target
)
left
= mid + 1;
else
if
(
a
[
mid
] >
target
)
right
= mid;
else
return mid;
}
return
-
1
;
}
/*
类型1写法二
*/
int
binarysearch
(
vector
<
int
>&
a
,
int
k
)
{
int
left
=
0
;
int
right
=
a
.
size
()
-
1
;
while
(
left
<=
right
)
{
int
mid
=
(
left
+
right
)
/
2
;
if
(
a
[
mid
]
<
k
)
//k较a[mid]大时,在右半区间找
left
=
mid
+
1
;
else
if
(
a
[
mid
]
>
k
)
//k较小时,在左半区间找
right
=
mid
-
1
;
else
//若想等则返回mid
return
mid
;
}
return
-
1
;
//找不到时返回-1
}
/* 类型2
功能:查找第一个大于等于目标值的数,可变形为查找最后一个小于目标值的数(返回
right-1)
完成
stl
中
lower_bound
的功能
返回:如果存在,返回对应位置索引,否则返回末尾索引end, 数组 [begin,end)
例:
[2, 4, 5, 6, 9]
,
target = 3
,返回数字
4
的位置;
[0, 1, 1, 1, 1]
,target = 1,返回第一个数字1的位置
过程:
left = 0,right = 5
mid = 2,a[2] = 1, right = mid = 2
mid = 1,a[1] = 1, right = mid = 1
mid = 0,a[0] < 1, left = mid+1 = 1 = right
跳出循环,然后
return
n1 n2(left) n3(right)
<a[mid] >=a[mid]
当a[mid]小于target时,left更新为mid+1,也就是说left之前的数一定是小于target的
而right更新的地方一定是≥target的
而循环会在left=right时退出,故right处的值是第一个≥target的数
*/
int
my_lowerbound
(
vector
<
int
>&
a
,
int
target
)
{
int
left
=
0
,
right
=
a
.
size
();
//
与
stl
中喜欢把
end
指向末尾后一个元素的做法类似
while
(
left
<
right
)
{
int
mid
=
left
+
(
right
-
left
)
/
2
;
if
(a[mid] < target)
left
=
mid
+
1
;
else
//没有单独考虑等于的情况
right
=
mid
;
}
return right;
}
/* 类型3
功能:查找第一个大于目标值的数,可变形为查找最后一个小于等于目标值的数(返回
right-1)
完成
stl
中
upper_bound
的功能
返回:如果存在,返回对应位置索引,否则返回末尾索引end, 数组 [begin,end)
例:
[2, 4, 5, 6, 9]
,
target = 3
,返回数字
4
的位置;
[0, 1, 1, 1, 1]
,target = 1,返回坐标5
,通过对比返回的坐标和数组的长度,我们就知道是否存在这样一个大于目标值的数
过程:
left = 0,right = 5
mid = 2,a[2] = 1, left = mid+1 = 3
mid = 4,a[4] = 1, left = mid+1 = 3 = right
跳出循环,然后
return
*/
int
my_upperbound
(
vector
<
int
>&
a
,
int
target
)
{
int
left
=
0
,
right
=
a
.
size
();
//
与
stl
中喜欢把
end
指向末尾后一个元素的做法类似
while
(
left
<
right
)
{
int
mid
=
left
+
(
right
-
left
)
/
2
;
if
(a[mid] <= target)
left
=
mid
+
1
;
else
right
=
mid
;
}
return
right
;
}