今天是第二个算法——二分法。
二分法
**引入:**来做个游戏:给你一个1~100之内的数字,你必须要在 7 次内猜出这个数字,怎么猜?
这个时候就要派上我们的二分法:
演示一下:
例如这个数是54,我问你7次:
大于等于50吗?是。(1~100二分,中位数是50)
大于等于75吗?否。(50~100二分,中位数是75)
大于等于63吗?否。(50~75二分,…)
大于等于56吗?否。
大于等于53吗?是。
大于等于54吗?是。
等于55吗?否。
那么这个数等于54。懂个大概了吗?
下面我来给出python的二分法模板:
def check(a,n,x):
left = 0
right = n
while left < right:
mid = left +(right-left)//2
if a[mid] >= x:
right = mid
else:
left = mid +1
print(a[mid])
return left
n = 100
test = 54
a = [0 for _ in range(1000)]
for i in range(n):
a[i] = i+1
print(a)
ans = check(a,n,test)
print('test = %d'%a[ans])
check() 操作 3个变量:区间左端点 left、右端点 right、二分的中位数 mid。每次把区间缩小一半,把 left 或 right 移动到 mid;直到 left = right 为止,即找到了答案所处的位置。
当 a[mid] >= x 时,说明 x 在 mid 的左边,新的搜索区间是左半部分,left 不变,更新 right = mid。
当 a[mid] < x 时,说明 x在 mid 的右边,新的搜索区间是右半部分,right 不变,更新 left = mid + 1。
代码执行完毕后,left = right,两者相等,即答案所处的位置。代码很高效,每次把搜索的范围缩小一半,总次数是 log(n)。
下面直接上例题:
题目描述
儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
小明一共有 N 块巧克力,其中第 i 块是 Hi ×Wi 的方格组成的长方形。为了公平起见,小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足:
1.形状是正方形,边长是整数;
2.大小相同;
例如一块6×5 的巧克力可以切出 6 块2×2 的巧克力或者 2 块3×3 的巧克力。
当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?
输入描述
第一行包含两个整数 N,K (1≤N,K≤10 5 )。
以下 N 行每行包含两个整数 Hi,Wi(1 <= Hi, Wi <= 105)。
输入保证每位小朋友至少能获得一块 1×1 的巧克力。
输出描述
输出切出的正方形巧克力最大可能的边长。
样例输入
2 10
6 5
5 6
样例输出
2
def check(d):
global w,h
res = 0
for i in range(len(w)):
res += (w[i]//d) * (h[i]//d)
if res >= k: return True
return False
n,k = map(int,input().split())
w = []
h = []
for i in range(n):
a,b = map(int,input().split())
w.append(a)
h.append(b)
L ,R = 1, 10000
while L < R:
mid = (L+R)//2
if check(mid): L = mid +1
else : R = mid
print(L-1)
这个题就是运用了二分法。
下课题见。