前言🍉
二分查找一个简单的算法,但是因为边界问题往往写不好。特此记录模板,以便快捷使用。
[二分查找]从列表q找到第一个>=k的数,返回位置👑
'''
[二分查找]从列表q找到第一个>=k的数,返回位置
'''
def bsearch_first(data, k):
# 设定左边界l=0, 右边界r=n-1(0-n-1为数组下标)
l, r = 0, len(data)-1
# 当左边界(l)!=右边界(r)
while l != r:
# 计算有序数组中间数据的索引
mid = l + r >> 1
# 如果列表中间的数据>=k,那么需要缩小右边界
# 比如:k=2,data=[1 2 3 4 5],那么中间数3比2大,所以缩小[1,2,3,4,5]变成r=[1,2,3]
if data[mid] >= k:
r = mid
# 反之缩小左边界
else:
l = mid + 1
if data[l] != k: # 不存在,返回-1
return -1
return l
[二分查找]从列表q找到最后一个<=k的数,返回位置👑
'''
[二分查找]从列表q找到最后一个<=k的数,返回位置
'''
def bsearch_last(data, k):
# 设定左边界l=0, 右边界r=n-1(0-n-1为数组下标)
l, r = 0, len(data)-1
# 当左边界(l)!=右边界(r)
while l != r:
# 计算有序数组中间数据的索引
mid = l + r + 1 >> 1
# 如果列表中间的数据<=k,那么需要缩小左边界
# 比如:k=4,data=[1 2 3 4 5],那么中间数3比4小,所以缩小[1,2,3,4,5]变成r=[4,5]
if data[mid] <= k:
l = mid
# 反之缩小右边界
else:
r = mid - 1
if data[l] != k: # 不存在,返回-1
return -1
return l
【例题】数的范围🍉
给定一个按照升序排列的长度为n的整数数组,以及q个查询。
对于每个查询,返回一个元素k的起始位置和终止位置(位置从0开始计数)
如果数组中不存在该元素,则返回“-1 -1\n”。
输入格式
第一行包含整数n和q,表示数组长度和询问个数。
第二行包含n个整数(均在1~10000范围内),表示完整数组。
接下来q行,每行包含一个整数k,表示一个询问元素。
输出格式
共q行,每行包含两个整数,表示所求元素的起始位置和终止位置。
如果数组中不存在该元素,则返回“-1 -1\n”。
数据范围
输入样例:
6 3
1 2 2 3 3 4
3
4
5
输出样例
3 4
5 5
-1 -1
AC Code:
'''
[二分查找]从列表q找到第一个>=k的数,返回位置
'''
def bsearch_first(data, k):
# 设定左边界l=0, 右边界r=n-1(0-n-1为数组下标)
l, r = 0, len(data)-1
# 当左边界(l)!=右边界(r)
while l != r:
# 计算有序数组中间数据的索引
mid = l + r >> 1
# 如果列表中间的数据>=k,那么需要缩小右边界
# 比如:k=2,data=[1 2 3 4 5],那么中间数3比2大,所以缩小[1,2,3,4,5]变成r=[1,2,3]
if data[mid] >= k:
r = mid
# 反之缩小左边界
else:
l = mid + 1
if data[l] != k: # 不存在,返回-1
return -1
return l
'''
[二分查找]从列表q找到最后一个<=k的数,返回位置
'''
def bsearch_last(data, k):
# 设定左边界l=0, 右边界r=n-1(0-n-1为数组下标)
l, r = 0, len(data)-1
# 当左边界(l)!=右边界(r)
while l != r:
# 计算有序数组中间数据的索引
mid = l + r + 1 >> 1
# 如果列表中间的数据<=k,那么需要缩小左边界
# 比如:k=4,data=[1 2 3 4 5],那么中间数3比4小,所以缩小[1,2,3,4,5]变成r=[4,5]
if data[mid] <= k:
l = mid
# 反之缩小右边界
else:
r = mid - 1
if data[l] != k: # 不存在,返回-1
return -1
return l
if __name__ == '__main__':
n, m = map(int, input().split())
q = list(map(int, input().split()))
for _ in range(m):
k = int(input())
print(bsearch_first(q, k), bsearch_last(q, k))
数的三次方根🍉
给定一个浮点数 n,求它的三次方根。
输入格式
共一行,包含一个浮点数 n。
输出格式
共一行,包含一个浮点数,表示问题的解。
注意,结果保留 6 位小数。
数据范围
输入样例:
1000.00
输出样例:
10.000000
AC code
n = float(input())
def bsearch(l, r):
while r - l > 1e-8: #浮点数二分法的循环条件是r-l<1e-8,其中8是因为题目中要保留6位小数
mid = float((l + r) /2)
if mid*mid*mid >= n:
r = mid
else:
l = mid
return l
l = bsearch(-10000, 10000)
print("{:.6f}".format(l))