当前位置: 首页 > ds >正文

单调队列深度解析(下)

单调队列深度解析-下

    • 一、单调队列在图论中的应用
      • 1. 问题背景
      • 2. 示例问题:最短路径上的最大边权
        • 算法思路
        • 代码实现(Python)
    • 二、单调队列在动态规划中的应用
      • 1. 问题背景
      • 2. 示例问题:最大子数组和(带限制长度)
        • 算法思路
        • 代码实现(Java)

在《单调队列深度解析(上)》中,我已经对单调队列的基本定义、算法思想、结构性质、使用步骤以及基本模板进行了详细的介绍。在本文中,我将深入探讨单调队列的进阶应用,包括在图论、动态规划等复杂场景中的使用,帮助大家对单调队列有更深刻的理解和更灵活的运用。

一、单调队列在图论中的应用

1. 问题背景

在图论中,有时我们需要在满足一定条件的路径上寻找最值。单调队列可以帮助我们在动态更新路径信息的过程中,高效地维护局部最值,从而优化算法的时间复杂度。

2. 示例问题:最短路径上的最大边权

假设有一个带权无向图 G=(V,E)G=(V, E)G=(V,E),我们要从起点 sss 到终点 ttt 寻找一条最短路径,并且我们关心这条最短路径上的最大边权。

算法思路

我们可以使用 Dijkstra 算法的变种来解决这个问题。在 Dijkstra 算法的优先队列中,我们通常存储的是到某个节点的最短距离。而在这里,我们除了存储最短距离外,还需要维护从起点到该节点的最短路径上的最大边权。在更新路径信息时,使用单调队列来维护这个最大边权。

代码实现(Python)
import heapq
from collections import dequedef shortest_path_max_edge_weight(graph, start, end):n = len(graph)dist = [float('inf')] * nmax_edge = [0] * ndist[start] = 0pq = [(0, 0, start)]  # (distance, max_edge_weight, node)while pq:d, me, node = heapq.heappop(pq)if d > dist[node]:continueif node == end:return mefor neighbor, weight in graph[node]:new_dist = d + weightnew_max_edge = max(me, weight)if new_dist < dist[neighbor]:dist[neighbor] = new_distmax_edge[neighbor] = new_max_edgeheapq.heappush(pq, (new_dist, new_max_edge, neighbor))return -1# 示例图的邻接表表示
graph = [[(1, 2), (2, 4)],[(0, 2), (2, 1), (3, 7)],[(0, 4), (1, 1), (3, 3)],[(1, 7), (2, 3)]
]
start = 0
end = 3
print(shortest_path_max_edge_weight(graph, start, end))

二、单调队列在动态规划中的应用

1. 问题背景

动态规划是解决许多优化问题的常用方法,但在某些情况下,状态转移的时间复杂度较高。单调队列可以帮助我们优化状态转移的过程,将时间复杂度从 O(n2)O(n^2)O(n2) 降低到 O(n)O(n)O(n)

2. 示例问题:最大子数组和(带限制长度)

给定一个整数数组 numsnumsnums 和一个整数 kkk,求长度不超过 kkk 的连续子数组的最大和。

算法思路

我们可以使用动态规划来解决这个问题。定义 dp[i]dp[i]dp[i] 表示以第 iii 个元素结尾的长度不超过 kkk 的连续子数组的最大和。状态转移方程为:

[dp[i]=max⁡j=max⁡(0,i−k)i−1(dp[j])+nums[i]][dp[i] = \max_{j = \max(0, i - k)}^{i - 1} (dp[j]) + nums[i]][dp[i]=maxj=max(0,ik)i1(dp[j])+nums[i]]

为了优化状态转移的过程,我们可以使用单调队列来维护 dp[j]dp[j]dp[j] 的最大值。

代码实现(Java)
import java.util.ArrayDeque;
import java.util.Deque;public class MaxSubarraySumWithLimit {public int maxSubarraySum(int[] nums, int k) {int n = nums.length;int[] dp = new int[n];dp[0] = nums[0];int maxSum = dp[0];Deque<Integer> deque = new ArrayDeque<>();deque.offerLast(0);for (int i = 1; i < n; i++) {// 移除不在窗口内的元素if (!deque.isEmpty() && i - deque.peekFirst() > k) {deque.pollFirst();}dp[i] = (deque.isEmpty() ? 0 : dp[deque.peekFirst()]) + nums[i];// 维护单调递减队列while (!deque.isEmpty() && dp[deque.peekLast()] <= dp[i]) {deque.pollLast();}deque.offerLast(i);maxSum = Math.max(maxSum, dp[i]);}return maxSum;}public static void main(String[] args) {MaxSubarraySumWithLimit solution = new MaxSubarraySumWithLimit();int[] nums = {1, -2, 3, -4, 5, -6};int k = 3;System.out.println(solution.maxSubarraySum(nums, k));}
}

总结
单调队列作为一种高效的数据结构,不仅在滑动窗口问题中表现出色,在图论动态规划等复杂场景中也能发挥重要作用。通过维护队列的单调性,我们可以在动态更新数据的过程中,快速找到局部最值,从而优化算法的时间复杂度

That’s all, thanks for reading~~
觉得有用就点个赞、收进收藏夹吧!关注我,获取更多干货~

http://www.xdnf.cn/news/15941.html

相关文章:

  • 前端开发技巧:浏览器模拟弱网络环境
  • 【Linux】重生之从零开始学习运维之Nginx
  • 高可用架构设计与实践综述
  • XSS总结
  • 【RK3576】【Android14】固件烧录
  • 零基础学后端-PHP语言(第一期-PHP环境配置)
  • SQL核心语法与实战应用指南
  • MacOS:如何利用终端来操作用户
  • kafka--基础知识点--6.1--LEO、HW、LW
  • 2025 Data Whale x PyTorch 安装学习笔记(Windows 版)
  • react+antd+表格拖拽排序以及上移、下移、移到顶部、移到底部
  • react17更新哪些新特性
  • ARINC818协议综述
  • 48Days-Day03 | 删除公共字符,两个链表的第一个公共结点,mari和shiny
  • uniapp相关地图 API调用
  • servicemesh 学习
  • 实战分享:Web3 前端开发Defi项目
  • [硬件电路-39]:激光光路的光信号处理、模拟电路的电信号处理、数字电路的电信号处理、软件的信号处理,有哪些共通的操作、运算、变换?
  • 06-人机共生:Prompt之外的思考
  • 【RK3576】【Android14】USB开发调试
  • k8s 基本架构
  • 【小沐学GIS】基于Rust绘制三维数字地球Earth(Rust、OpenGL、GIS)
  • 完美解决 Ubuntu 中自定义启动器图标重复的问题(以 MATLAB 为例)
  • bash方式启动模型训练
  • python基础复习
  • 高压电工作业证考试核心考点:电气安全基础篇
  • 响应式单位rpx及搭配使用UI产品工具
  • 风格多样!5 个覆盖全风格的素材网站,创作有新意
  • AUTOSAR进阶图解==>AUTOSAR_SWS_DiagnosticOverIP
  • 创建套接字并bind的详细过程