关于二分查找

Posted 金带头鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于二分查找相关的知识,希望对你有一定的参考价值。

二分查找的局限性:

    必须是顺序表结构,  不能是链表等结构

    数据是有序的

    数据量太小不适合二分查找

    数据量太大也不适合, 二分查找底层依赖数组这种数据结构, 而数据需要连续内存空间 — 对内存要求苛刻


二分查找需要考虑的细节

    终止条件

    区间上下界更新方法

    返回值选择


二分查找时不要把思维局限于一定要对排序的数据, 且只能用于查找相关数据

对应的例子在文中的 leetcode 410题

考虑 问题的上界是什么 / 下界是什么 状态怎么取]

二分的另一种比较常见的题型是在处理区间和的问题上


凡是能用二分查找解决的基本都可以用散列表或二叉查找树也能处理

二分查找更适合应用于处理 "近似"查找的问题



一个二分查找的实际应用




# 基本的二分查找a = [1, 2,3, 4,5,6,7,8,9]def find(x): start, end = 0, len(a) last = "" while start <= end: mid = (start+end) // 2 if mid == last: break if a[mid] == x: return mid elif a[mid] > x: end = mid else: start = mid last = mid return -1

二分查找的变形题

    查找第一个值等于给定的元素

    查找最后一个值等于给定值的元素

    查找第一个大于等于给定值的元素

    查找最后一个小于等于给定值的元素

    因为这四个类型都算是一个套路的, 所以在下面的代码里面备注显示

# 查找第一个值等于给定的元素# 查找最后一个值等于给定值的元素# 查找第一个大于等于给定值的元素# 查找最后一个小于等于给定值的元素
a = [1, 2,3, 4,5,6,7,7,7,7,7,7,8,9]def find(x): start, end = 0, len(a) last = "" while start <= end: mid = (start+end) // 2 if mid == last: break        if a[mid] == x:  # 查找第一个的场景 if mid == 0 or a[mid-1] != x: return mid end = mid        if a[mid] == x:  # 查找最后一个的场景 if mid == len(a)-1 or a[mid+1] != x: return mid start = mid         if a[mid] == x:  # 查找第一小于给定值的元素 if mid == 0: return -1 elif a[mid-1] != x: return a[mid-1]            end = mid        if a[mid] == x: # 查找第一个大于给定值的元素 if mid == len(a)-1: return -1 elif a[mid+1] != x: return a[mid+1]            start = mid elif a[mid] > x: end = mid else: start = mid last = mid return -1


一些leetcode上的二分查找相关题目

# leetcode 410题给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。设计一个算法使得这 m 个子数组各自和的最大值最小。nums = [7,2,5,10,8]m = 2输出:18class Solution: def splitArray(self, nums: List[int], m: int) -> int: left = max(nums) right = sum(nums)  def check(val): count, sval = 1, 0 for i in nums: if sval + i > val: count += 1 sval = i else: sval += i return count <= m
while left < right: mid = (left + right) // 2 if check(mid): right = mid else: left = mid+1 return left


如果是完全利用题目给的二维矩阵的性质 就需要用二分查找

使用部分性质 那就用归并

# leetcode 378题给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素。class Solution: def kthSmallest(self, matrix: List[List[int]], k: int) -> int: n = len(matrix)
def check(mid): i, j = n - 1, 0 num = 0 while i >= 0 and j < n: if matrix[i][j] <= mid: num += i + 1 j += 1 else: i -= 1 return num >= k
left, right = matrix[0][0], matrix[-1][-1] while left < right: mid = (left + right) // 2 if check(mid): right = mid else: left = mid + 1 return left

以上是关于关于二分查找的主要内容,如果未能解决你的问题,请参考以下文章

关于二分查找

关于二分查找

关于二分查找

二分查找

关于二分查找的一些思考

关于二分查找及变体