codeforces-go中的二分查找:实现实例
还在为算法竞赛中的二分查找烦恼吗?一文掌握codeforces-go项目中最实用的二分查找实现技巧!
读完本文,你将收获:
- ✅ 二分查找的核心原理与使用场景
- ✅ Go标准库sort.Search的实战技巧
- ✅ 四种常见二分查找变体的代码实现
- ✅ 实际竞赛题目的应用案例
📊 二分查找基础概念
二分查找(Binary Search)是一种高效的查找算法,时间复杂度为O(log n)。在算法竞赛中,二分查找常用于:
- 有序数组查找:快速定位目标元素
- 二分答案:求解最优解问题
- 最大化/最小化问题:如最大化最小值、最小化最大值
- 第K小/大问题:快速定位排序后的第K个元素
🔧 Go标准库二分查找用法
codeforces-go项目在copypasta/sort.go中详细展示了Go标准库sort.Search的使用方法:
// 基本二分查找用法
func binarySearch(a []int, target int) int {
return sort.SearchInts(a, target) // 返回>=target的第一个下标
}
四种边界情况处理
a := []int{1, 3, 5, 7, 9}
x := 5
lowerBound := sort.SearchInts(a, x) // >=x的第一个下标
upperBound := sort.SearchInts(a, x+1) // >x的第一个下标
lastLE := sort.SearchInts(a, x+1) - 1 // <=x的最后一个下标
lastLT := sort.SearchInts(a, x) - 1 // <x的最后一个下标
🎯 二分查找四大变体实战
1. 二分答案(最大化最小值)
// 最大化最小值:让最小值尽可能大
func maximizeMin(a []int, k int) int {
return sort.Search(maxValue, func(x int) bool {
x++ // 关键技巧:判断x+1是否满足
cnt := 0
for _, v := range a {
if v >= x {
cnt++
}
}
return cnt < k // 不满足要求返回true
})
}
2. 二分答案(最小化最大值)
// 最小化最大值:让最大值尽可能小
func minimizeMax(a []int, k int) int {
return sort.Search(maxValue, func(x int) bool {
cnt := 0
for _, v := range a {
if v <= x {
cnt++
}
}
return cnt >= k // 满足要求返回true
})
}
3. 第K小元素查找
// 在有序矩阵中查找第K小元素
func kthSmallest(matrix [][]int, k int) int {
n := len(matrix)
low, high := matrix[0][0], matrix[n-1][n-1]
return low + sort.Search(high-low, func(mid int) bool {
mid += low
count := 0
// 统计<=mid的元素个数
for i, j := 0, n-1; i < n && j >= 0; {
if mid < matrix[i][j] {
j--
} else {
count += j + 1
i++
}
}
return count >= k
})
}
4. 0-1分数规划
// 求解最大比率问题
func search01(ps [][2]int, k int) float64 {
// 二分求解∑ai/∑bi的最大值
l, r := -1.0, 1e5+1
const eps = 1e-8
for step := 0; step < 100; step++ {
mid := (l + r) / 2
arr := make([]float64, len(ps))
for i, p := range ps {
arr[i] = float64(p[0]) - mid*float64(p[1])
}
sort.Float64s(arr)
sum := 0.0
for _, v := range arr[len(arr)-k:] {
sum += v
}
if sum < 0 {
r = mid
} else {
l = mid
}
}
return (l + r) / 2
}
🏆 实际应用案例
案例1:Car Fleet问题
在leetcode/weekly/853中有Car Fleet问题的二分查找解法,通过排序+二分快速计算车队数量。
案例2:借教室问题
经典的借教室问题(Luogu P1083)可以通过二分答案+差分数组解决,在copypasta/sort.go中有详细实现思路。
案例3:最大化运行时间
在main/1900-1999/中有多题使用二分答案来最大化计算机运行时间,展现了二分查找在优化问题中的强大能力。
💡 使用技巧与注意事项
- 边界处理:始终注意数组边界,避免越界访问
- 整数溢出:在计算mid时使用
int(uint(l+r)>>1)避免溢出 - 精度控制:实数二分时,eps通常设为要求精度+2个数量级
- 单调性验证:确保二分函数f(x)具有单调性
📚 扩展学习
- 二分算法题单 - 灵茶山艾府整理的二分专题
- 算法竞赛进阶指南 - 包含丰富的二分查找应用
- OI Wiki二分查找 - 系统性的二分查找教程
掌握这些二分查找技巧,你将能轻松解决算法竞赛中60%以上的二分相关问题。多练习、多思考,二分查找将成为你的得力工具!
如果觉得本文对你有帮助,请点赞⭐收藏📁,我们下期再见!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




