Python高级算法与数据结构优化实战

news2025/3/15 7:13:11

Python高级算法与数据结构优化实战

在算法竞赛中,掌握高级优化技巧和数据结构实现可以显著提升解题效率和代码性能。本文深入探讨Python中常见算法问题的高效实现方法,通过实际比赛案例展示如何优化时间复杂度和空间复杂度。

一、前缀和与差分数组

前缀和与差分数组是算法竞赛中处理区间查询和修改的利器,能将时间复杂度从O(n)降至O(1)。

1.1 前缀和技术

基本实现:

def build_prefix_sum(nums):
    n = len(nums)
    prefix = [0] * (n + 1)
    for i in range(n):
        prefix[i + 1] = prefix[i] + nums[i]
    return prefix

def range_sum(prefix, left, right):
    # 返回nums[left]到nums[right-1]的和
    return prefix[right] - prefix[left]

实战应用: 矩阵区域和

题目: 计算二维矩阵中任意子矩阵的元素和。

def matrix_region_sum(matrix):
    if not matrix or not matrix[0]:
        return []
    
    m, n = len(matrix), len(matrix[0])
    # 构建二维前缀和
    prefix = [[0] * (n + 1) for _ in range(m + 1)]
    
    for i in range(m):
        for j in range(n):
            prefix[i + 1][j + 1] = prefix[i + 1][j] + prefix[i][j + 1] - prefix[i][j] + matrix[i][j]
    
    # 查询函数: 返回(row1,col1)到(row2,col2)矩形区域的和
    def query(row1, col1, row2, col2):
        return prefix[row2 + 1][col2 + 1] - prefix[row2 + 1][col1] - prefix[row1][col2 + 1] + prefix[row1][col1]
    
    return query

# 示例
matrix = [
    [3, 0, 1, 4, 2],
    [5, 6, 3, 2, 1],
    [1, 2, 0, 1, 5],
    [4, 1, 0, 1, 7],
    [1, 0, 3, 0, 5]
]

region_sum = matrix_region_sum(matrix)
print(region_sum(1, 1, 3, 3))  # 矩阵中(1,1)到(3,3)区域的和: 6+3+2+0+1

高级应用: 子数组和为k的个数

题目: 给定一个数组和整数k,求数组中和为k的连续子数组个数。

from collections import defaultdict

def subarray_sum_equals_k(nums, k):
    count = 0
    prefix_sum = 0
    # 前缀和出现次数的哈希表
    prefix_count = defaultdict(int)
    prefix_count[0] = 1  # 空前缀
    
    for num in nums:
        prefix_sum += num
        # 如果prefix_sum - k在哈希表中,说明存在前缀和为k的子数组
        count += prefix_count[prefix_sum - k]
        prefix_count[prefix_sum] += 1
    
    return count

# 示例
nums = [1, 1, 1]
k = 2
print(subarray_sum_equals_k(nums, k))  # 输出: 2

1.2 差分数组技术

差分数组是前缀和的逆运算,常用于区间更新操作。

基本实现:

def build_difference_array(nums):
    n = len(nums)
    diff = [0] * n
    diff[0] = nums[0]
    for i in range(1, n):
        diff[i] = nums[i] - nums[i - 1]
    return diff

def range_add(diff, left, right, val):
    # 将nums[left]到nums[right]的元素都加上val
    diff[left] += val
    if right + 1 < len(diff):
        diff[right + 1] -= val

def reconstruct_array(diff):
    n = len(diff)
    nums = [0] * n
    nums[0] = diff[0]
    for i in range(1, n):
        nums[i] = nums[i - 1] + diff[i]
    return nums

实战应用: 航班预订统计

题目: 有n个航班,航班编号从1到n。有多个预订记录,每个记录包含(first, last, seats),表示从first到last号航班预订了seats个座位。求每个航班预订的座位总数。

def corporate_flight_bookings(bookings, n):
    # 初始化差分数组
    diff = [0] * (n + 1)
    
    # 处理预订记录
    for first, last, seats in bookings:
        diff[first - 1] += seats     # 注意索引从0开始
        diff[last] -= seats          # 结束后恢复
    
    # 还原原始数组
    result = [0] * n
    result[0] = diff[0]
    for i in range(1, n):
        result[i] = result[i - 1] + diff[i]
    
    return result

# 示例
bookings = [[1, 2, 10], [2, 3, 20], [2, 5, 25]]
n = 5
print(corporate_flight_bookings(bookings, n))  # 输出: [10, 55, 45, 25, 25]

二、并查集(Union-Find)

并查集是处理元素分组和合并操作的高效数据结构,广泛应用于图论问题。

2.1 并查集的高效实现

class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n  # 按秩合并优化
        self.count = n       # 连通分量数
    
    def find(self, x):
        if self.parent[x] != x:
            # 路径压缩
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def union(self, x, y):
        root_x = self.find(x)
        root_y = self.find(y)
        
        if root_x == root_y:
            return False
        
        # 按秩合并
        if self.rank[root_x] < self.rank[root_y]:
            self.parent[root_x] = root_y
        elif self.rank[root_x] > self.rank[root_y]:
            self.parent[root_y] = root_x
        else:
            self.parent[root_y] = root_x
            self.rank[root_x] += 1
        
        self.count -= 1
        return True
    
    def connected(self, x, y):
        return self.find(x) == self.find(y)

实战应用: 岛屿数量问题

题目: 给定一个由 ‘1’(陆地)和 ‘0’(水)组成的二维网格,计算岛屿的数量。

def num_islands(grid):
    if not grid or not grid[0]:
        return 0
    
    m, n = len(grid), len(grid[0])
    uf = UnionFind(m * n)
    
    # 将水域标记为已访问
    land_count = 0
    for i in range(m):
        for j in range(n):
            if grid[i][j] == '1':
                land_count += 1
            else:
                # 水域节点的父节点设为一个特殊值
                uf.parent[i * n + j] = -1
    
    # 方向数组: 右、下
    directions = [(0, 1), (1, 0)]
    
    # 合并相邻的陆地
    for i in range(m):
        for j in range(n):
            if grid[i][j] == '1':
                current = i * n + j
                # 检查右边和下边的相邻节点
                for dx, dy in directions:
                    ni, nj = i + dx, j + dy
                    if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == '1':
                        neighbor = ni * n + nj
                        uf.union(current, neighbor)
    
    # 计算连通分量数量
    islands = 0
    for i in range(m * n):
        if uf.parent[i] != -1 and uf.find(i) == i:
            islands += 1
    
    return islands

# 示例
grid = [
    ["1","1","0","0","0"],
    ["1","1","0","0","0"],
    ["0","0","1","0","0"],
    ["0","0","0","1","1"]
]
print(num_islands(grid))  # 输出: 3

高级应用: 最小生成树的Kruskal算法

def kruskal_mst(n, edges):
    """
    Kruskal算法求最小生成树
    n: 节点数
    edges: 边列表 [(u, v, weight)]
    返回: 最小生成树的总权重
    """
    # 按权重排序
    edges.sort(key=lambda x: x[2])
    
    uf = UnionFind(n)
    mst_weight = 0
    mst_edges = []
    
    for u, v, weight in edges:
        if uf.union(u, v):  # 如果合并成功(不会形成环)
            mst_weight += weight
            mst_edges.append((u, v, weight))
        
        # 如果已经找到n-1条边,说明最小生成树已完成
        if len(mst_edges) == n - 1:
            break
    
    return mst_weight, mst_edges

# 示例
edges = [
    (0, 1, 10), (0, 2, 6), (0, 3, 5),
    (1, 3, 15), (2, 3, 4)
]
n = 4
weight, mst = kruskal_mst(n, edges)
print(f"最小生成树权重: {
     weight}")
print(f"最小生成树边: {
     mst}")

三、线段树与树状数组

线段树和树状数组是处理区间查询和区间修改的高级数据结构。

3.1 树状数组(Binary Indexed Tree)

树状数组在O(log n)时间内完成单点更新和前缀和查询。

class BinaryIndexedTree:
    def __init__(self, n):
        self.size = n
        self.tree = [0] * (n + 1)  # 索引从1开始
    
    def update(self, index, delta):
        """更新单个元素"""
        while index <= self.size:
            self.tree[index] += delta
            index += (index & -index)  # 加上最低位的1
    
    def query(self, index):
        """查询前缀和: 从1到index的元素和"""
        result = 0
        while index > 0:
            result += self.tree[index]
            index -= (index & -index)  # 减去最低位的1
        return result
    
    def range_query(self, left, right):
        """查询区间和: 从left到right的元素和"""
        return self.query(right) - self.query(left - 1)

实战应用: 逆序对计数

题目: 计算一个数组中的逆序对数量。逆序对是指数组中的两个元素,前面的元素大于后面的元素。

def count_inversions(nums):
    # 离散化: 将数组中的元素映射到1到n
    sorted_nums = sorted(set(nums))
    rank = {
   val: idx + 1 for idx, val in enumerate(s

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2315314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 Excel 实现绩效看板的自动化

引言 在日常工作中&#xff0c;团队的绩效监控和管理是确保项目顺利进行的重要环节。然而&#xff0c;面临着以下问题&#xff1a; ​数据分散&#xff1a;系统中的数据难以汇总&#xff0c;缺乏一个宏观的团队执行情况视图。​看板缺失&#xff1a;系统本身可能无法提供合适…

vue3怎么和大模型交互?

引言 平时我们都是用的在线的AI工具&#xff0c;直接输入问题&#xff0c;然后AI回答我们&#xff0c;那么怎么把AI接入项目中呢&#xff1f; 这个问题问得好。 方案一&#xff1a;引入第三方已封装好的UI库方案二&#xff1a;自己写 对于方案一&#xff0c;市面上已有一些…

【网络编程】HTTP网络编程

13.1 HTTP 简介 HTTP(Hyper Text Transfer Protocol,超文本传输协议)是用于从万维网(WWW:World Wide Web) 服务器(简称Web 服务器)传输超文本到本地浏览器的传送协议&#xff0c;基于TCP/IP 通信协 议来传递数据 (HTML 文件、图片文件、查询结果等)。 13.2 HTTP 的工作原理 …

【Qt】QWidget属性介绍

&#x1f3e0;个人主页&#xff1a;Yui_ &#x1f351;操作环境&#xff1a;Qt Creator &#x1f680;所属专栏&#xff1a;Qt 文章目录 前言1. enabled属性2.geometry属性2.1 改变控件位置2.2 女神表白程序2.3 知识补充——window frame 3. windowsTitle属性4. windowIcon属性…

『Rust』Rust运行环境搭建

文章目录 rust编译工具rustupVisual Studio VS Code测试编译手动编译VSCode编译配置 参考完 rust编译工具rustup https://www.rust-lang.org/zh-CN/tools/install 换源 RUSTUP_DIST_SERVER https://rsproxy.cn RUSTUP_UPDATE_ROOT https://rsproxy.cn修改rustup和cargo的安…

vue/react/vite前端项目打包的时候加上时间最简单版本,防止后端扯皮

如果你是vite项目&#xff0c;直接写一个vite的插件&#xff0c;通过这个插件可以动态注入环境变量&#xff0c;然后当打包的时候&#xff0c;自动注入这个时间到环境变量中&#xff0c;然后在项目中App.vue中或者Main.tsx中打印出来&#xff0c;这就知道是什么时候编译的项目了…

Cadence学习笔记3

设置 PCB 层叠 初始我们有一个两层板&#xff0c;如果需要添加层叠怎么办&#xff1f; 点击进入层叠设置 首先右击 TOP 层下面的空白&#xff0c;然后鼠标右键进行 add layer 然后选择 Plane(一般层就是这个&#xff09; 就好 然后 add就行 设置光标显示形式 在 setup ->…

Linux系统下如何部署svmspro平台

上传svmspro服务 rz回车后选择svmspro.zip上传如果提示rz命令未找到&#xff0c;请先运行 yum install -y lrzsz 安装将svmspro.zip解压出来&#xff0c;并拷贝到/usr/目录下&#xff0c;命令如下&#xff1a; unzip svmspro.zip//解压程序包cp svmspro /usr/ -r//将svmspro文件…

vue3:八、登录界面实现-忘记密码

一、页面效果 二、实现 1、视图层 <el-form-item class"flex flex-between"><el-checkbox label"记住密码" v-model"remember" /> </el-form-item> 参考 Checkbox 多选框 | Element Plus 2、逻辑层 首先设置记住密码的变…

el-table树形表格合并相同的值

el-table树形表格合并相同的值 el-table树形表格合并相同的值让Ai进行优化后的代码 el-table树形表格合并相同的值 <style lang"scss" scoped> .tableBox {/deep/ &.el-table th:first-child,/deep/ &.el-table td:first-child {padding-left: 0;} } …

Apache Tomcat漏洞,对其进行升级

我们付出一些成本&#xff0c;时间的或者其他&#xff0c;最终总能收获一些什么。 升级背景&#xff1a; 近日&#xff0c;新华三盾山实验室监测到 Apache 官方修复了一个远程代码执行漏洞 (CVE-2025-24813) &#xff0c;其CVSS3 漏洞评分为 7.5 。 影响范围 9.0.0.M1 ≤…

工程实践:如何使用SU17无人机来实现室内巡检任务

阿木实验室最近发布了科研开发者版本的无人机SU17&#xff0c;该无人机上集成了四目视觉&#xff0c;三维激光雷达&#xff0c;云台吊舱&#xff0c;高算力的机载计算机&#xff0c;是一个非常合适的平台用于室内外巡检场景。同时阿木实验室维护了多个和无人机相关的开源项目。…

OSPF-3 1类LSA Router LSA

前面两期我们介绍了OSPF的邻居与邻接建立的关系及失败因素和原因 这章我们来说说OSPF是如何通过不同的LSA去描述拓扑的信息以及路由信息 一、概述 OSPF通过不同的LSA来构成LSDB链路状态数据库,再通过SPF算法来计算出最优的最短路径 二、LSA的分类 类型名称描述传播范围1类…

【清华大学第七版】DeepSeek赋能家庭教育的实操案例(批改作文+辅助语文/数学/科学学习+制定学习计划)

我用夸克网盘分享了「DeepSeek完整资料合集」&#xff0c;点击链接即可保存。打开「夸克APP」&#xff0c;无需下载在线播放视频&#xff0c;畅享原画5倍速&#xff0c;支持电视投屏。 链接&#xff1a;https://pan.quark.cn/s/621259e4af15 近日&#xff0c;清华大学发布了《…

HCIA-ACL实验

前提条件&#xff1a;实现底层互通 转发层面 1、基本ACL ①要求PC3不能访问网段192.168.2.0的网段&#xff0c;PC4和客户端能正常访问服务器 ②AR2配置 acl 2000 rule deny source 192.168.1.1 0 匹配流量 int g 0/0/0 traffic-filter inbound acl 2000 接口调用…

DeepLabv3+改进10:在主干网络中添加LSKBlock|动态调整其大型空间感受野,助力小目标识别

🔥【DeepLabv3+改进专栏!探索语义分割新高度】 🌟 你是否在为图像分割的精度与效率发愁? 📢 本专栏重磅推出: ✅ 独家改进策略:融合注意力机制、轻量化设计与多尺度优化 ✅ 即插即用模块:ASPP+升级、解码器 PS:订阅专栏提供完整代码 目录 论文简介 步骤一 步骤二…

词向量:优维大模型语义理解的深度引擎

★ 放闸溯源 优维大模型「骨架级」技术干货 第二篇 ⇓ 词向量是Transformer突破传统NLP技术瓶颈的核心&#xff0c;它通过稠密向量空间映射&#xff0c;将离散符号转化为连续语义表示。优维大模型基于词向量技术&#xff0c;构建了运维领域的“语义地图”&#xff0c;实现从…

编译原理:语法分析程序【附源码和超详细注释】

目录 一 、实验目的 二 、实验内容及步骤 三、程序分析 1. 需求分析 2. 功能分析 1. LL(1)文法功能分析 2. 算符优先文法功能分析 3. 信创分析-主要针对能力提升中国产操作系统上开发内容。 四、源代码 1. LL(1)文法代码 2. 算符优先文法 五、测试结果 1. LL(1)文…

使用Flask和OpenCV 实现树莓派与客户端的视频流传输与显示

使用 Python 和 OpenCV 实现树莓派与客户端的视频流传输与显示 在计算机视觉和物联网领域&#xff0c;经常需要将树莓派作为视频流服务器&#xff0c;通过网络将摄像头画面传输到客户端进行处理和显示。本文将详细介绍如何利用picamera2库、Flask 框架以及 OpenCV 库&#xff…

fs的proxy_media模式失效

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 在fs的使用过程中&#xff0c;某些场景只需要对rtp媒体做透传&#xff0c;又不需要任何处理。 在fs1.6的版本中&#xff0c;我们可以使用proxy_media来代理媒体的转发&#xff0c;媒体的协商由AB路端对端处理&#xff…