Python二分枚举

二分枚举算法结合了二分查找和枚举的思想,主要用于在有序数据可二分性质的问题中高效寻找解决方案。

一、基本概念

二分查找 (Binary Search)

  • 核心思想:在有序数组中,通过不断缩小搜索范围来快速定位目标
  • 时间复杂度:O(log n)
  • 前提条件:数据必须是有序的

枚举 (Enumeration)

  • 核心思想:系统地尝试所有可能的候选解
  • 二分枚举是对传统枚举的优化,利用问题的单调性减少尝试次数

二、标准二分查找实现

问题:寻找第一个等于目标的元素

def first_occurrence(arr, target):
    left, right = 0, len(arr) - 1
    result = -1
    
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] >= target:
            right = mid - 1
            if arr[mid] == target:
                result = mid
        else:
            left = mid + 1
    
    return result

问题:寻找方程近似解

## 区间内只有一个解
def find_root(f, low, high, epsilon=1e-6):
    while high - low > epsilon:
        mid = (low + high) / 2
        if f(mid) * f(low) < 0:
            high = mid
        else:
            low = mid
    return (low + high) / 2

问题:平方根计算

def my_sqrt(x):
    if x < 2:
        return x
    
    left, right = 1, x // 2
    while left <= right:
        mid = (left + right) // 2
        if mid * mid == x:
            return mid
        elif mid * mid < x:
            left = mid + 1
        else:
            right = mid - 1
    
    return right  # 返回整数部分

### 二分图匹配的Python实现 以下是基于匈牙利算法(Hungarian Algorithm)的一个简单示例,该算法能够高效求解二分图的最大匹配问题。此代码实现了深度优先搜索版本的匈牙利算法。 #### 匈牙利算法的核心逻辑 通过构建邻接表表示二分图中的边关系,并利用递归函数寻找增广路径来更新当前匹配状态。最终返回的是最大匹配的数量以及具体的匹配结果[^2]。 ```python def hungarian_algorithm(graph): """ 使用匈牙利算法计算二分图的最大匹配。 :param graph: 邻接矩阵形式的二分图 (X -> Y 的连接情况),graph[i][j]=1 表示 X_i 和 Y_j 连通 :return: 最大匹配数, 具体匹配对 """ n_x = len(graph) # 左侧节点数量 n_y = len(graph[0]) if n_x > 0 else 0 # 右侧节点数量 match_to_y = [-1] * n_y # 记录右侧节点被哪个左侧节点匹配 (-1 表示未匹配) visited = None # 当前轮次访问标记数组 def dfs(x): """尝试为左侧节点 x 找到一个匹配""" for y in range(n_y): # 枚举右侧所有节点 if graph[x][y] and not visited[y]: # 如果存在边且尚未访问过 visited[y] = True # 标记已访问 if match_to_y[y] == -1 or dfs(match_to_y[y]): # 若 y 尚未匹配 或 能调整现有匹配 match_to_y[y] = x # 更新匹配关系 return True return False count = 0 # 统计最大匹配数目 for x in range(n_x): # 对每一个左侧节点执行 DFS 寻找增广路径 visited = [False] * n_y # 初始化本轮访问标志 if dfs(x): # 成功找到新的匹配 count += 1 matches = [(match_to_y[y], y) for y in range(n_y) if match_to_y[y] != -1] # 提取具体匹配对 return count, matches # 测试用例 if __name__ == "__main__": # 定义二分图的邻接矩阵 (左集合大小=4, 右集合大小=5) adj_matrix = [ [1, 1, 0, 0, 0], [0, 1, 0, 1, 0], [0, 0, 1, 1, 0], [0, 0, 0, 0, 1] ] max_matching_count, matching_pairs = hungarian_algorithm(adj_matrix) print(f"最大匹配数: {max_matching_count}") print("具体匹配:") for pair in matching_pairs: print(f"X_{pair[0]} <-> Y_{pair[1]}") ``` 上述代码展示了如何定义并解决问题中的二分图结构,同时提供了清晰的结果展示方式[^4]。 --- #### 关键点解析 1. **邻接矩阵**:`graph` 参数是一个二维列表,其中 `graph[i][j]==1` 表明第 i 个左侧顶点与第 j 个右侧顶点之间有一条边[^1]。 2. **DFS 增广路径查找**:核心在于递归调用 `dfs()` 函数,在满足条件的情况下不断扩展路径直至无法再延伸为止。 3. **时间复杂度分析**:由于每次操作最多涉及 V×E 条边遍历,因此整体性能较为优越[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值