news 2026/6/11 21:33:25

别再死记硬背了!用‘双队列’思路秒解PTA银行排队题,附Python/Java双版本代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再死记硬背了!用‘双队列’思路秒解PTA银行排队题,附Python/Java双版本代码

双队列调度实战:从PTA银行排队题到高并发任务处理

在编程竞赛和面试中,队列是最基础却最常考的数据结构之一。今天我们不只讲解一道PTA题目,而是深入剖析"双队列调度"这一经典模式,它不仅能解决银行窗口排队问题,还能应用于CPU任务调度、消息队列处理等真实场景。我们将通过Python和Java两种现代语言的实现,展示如何用更优雅的方式处理这类问题。

1. 理解双队列调度模型

双队列调度本质上是一种多通道差异化服务系统的抽象。在银行场景中,A窗口处理速度是B窗口的两倍,这类似于计算机系统中的优先级队列:高优先级任务获得更多计算资源。

这类问题的核心特征包括:

  • 存在多个服务通道(窗口、队列、处理器等)
  • 各通道服务速率不同(通常成简单整数比)
  • 有明确的分流规则(如奇偶分流、优先级判断)
  • 需要按完成顺序输出结果

关键识别点:当题目描述中出现"不同处理速度"、"按某种规则分流"、"按完成顺序输出"等关键词时,很可能适用双队列模型。

2. 问题分析与抽象化思考

原题描述银行有两个窗口,A窗口处理速度是B窗口的两倍。顾客根据编号奇偶分流,最终按业务完成顺序输出。我们需要将其抽象为通用模型:

输入: - N个任务/顾客 - 分流规则(如奇偶性) - 各队列处理速度比(如2:1) 处理: - 根据规则将任务分配到不同队列 - 按照速度比从各队列取出任务处理 - 某一队列空时自动切换到另一队列 输出: - 按任务完成顺序排列的结果

这种抽象使得解决方案能应用于各类相似场景,如:

  • 多核CPU任务调度
  • 网络请求分流处理
  • 工厂生产线优化

3. Python实现与collections.deque妙用

Python的collections.deque是实现队列的理想选择,相比列表(list)在头部操作上有O(1)时间复杂度。下面是Python实现:

from collections import deque def bank_queue_simulation(customers): queue_a = deque() queue_b = deque() # 分流阶段 for customer in customers: if customer % 2 == 1: # 奇数 queue_a.append(customer) else: # 偶数 queue_b.append(customer) result = [] a_len, b_len = len(queue_a), len(queue_b) total = a_len + b_len # 处理阶段 for i in range(1, total + 1): if not queue_a: # A队列空 result.append(queue_b.popleft()) elif not queue_b: # B队列空 result.append(queue_a.popleft()) elif i % 3 == 0: # 每第三个从B出队 result.append(queue_b.popleft()) else: # 其他从A出队 result.append(queue_a.popleft()) return result # 示例使用 customers = [2, 1, 3, 9, 4, 11, 13, 15] print(bank_queue_simulation(customers)) # 输出: [1, 3, 2, 9, 11, 4, 13, 15]

代码亮点分析

  1. 使用deque替代列表提升性能
  2. 清晰的两个阶段:分流→处理
  3. 通过模运算(i%3)实现2:1处理比例
  4. 队列空检查确保健壮性

4. Java实现与LinkedList选择

Java中LinkedList实现了Queue接口,是队列操作的经典选择。下面是Java实现:

import java.util.LinkedList; import java.util.Queue; public class BankQueue { public static int[] simulateBankQueue(int[] customers) { Queue<Integer> queueA = new LinkedList<>(); Queue<Integer> queueB = new LinkedList<>(); // 分流阶段 for (int customer : customers) { if (customer % 2 != 0) { queueA.add(customer); } else { queueB.add(customer); } } int total = customers.length; int[] result = new int[total]; int index = 0; // 处理阶段 for (int i = 1; i <= total; i++) { if (queueA.isEmpty()) { result[index++] = queueB.poll(); } else if (queueB.isEmpty()) { result[index++] = queueA.poll(); } else if (i % 3 == 0) { result[index++] = queueB.poll(); } else { result[index++] = queueA.poll(); } } return result; } public static void main(String[] args) { int[] customers = {2, 1, 3, 9, 4, 11, 13, 15}; int[] result = simulateBankQueue(customers); for (int num : result) { System.out.print(num + " "); } // 输出: 1 3 2 9 11 4 13 15 } }

Java实现特点

  1. 使用Queue接口编程,LinkedList作为具体实现
  2. poll()方法安全获取并移除队列头部
  3. isEmpty()检查比Python的not queue更显式
  4. 数组预分配提升性能

5. 解题模板与举一反三

基于以上分析,我们可以总结出双队列调度问题的通用解题模板:

  1. 初始化阶段

    • 创建两个队列
    • 定义分流规则(如奇偶、优先级等)
  2. 分流阶段

    • 遍历输入元素
    • 根据规则将元素分配到不同队列
  3. 处理阶段

    • 确定处理比例(如2:1、3:1等)
    • 按比例交替从队列取出元素
    • 处理队列空的情况
  4. 输出阶段

    • 收集处理结果
    • 按要求格式化输出

变种问题识别表

问题特征可能变种解决方案调整
窗口/队列数量变化三队列调度增加队列,调整处理比例
处理速度比例变化3:1而非2:1修改模运算基数
动态分流规则基于数值范围而非奇偶修改分流条件判断
加入到达时间考虑顾客到达时间间隔引入时间变量模拟

6. 性能优化与边界情况

在实际编码中,我们需要考虑以下优化点和边界情况:

优化建议

  • 预分配结果数组/列表空间(如Java实现所示)
  • 在分流阶段同时计数队列长度,避免后续反复计算
  • 对于固定处理比例,可以用计数器替代模运算

边界情况处理

  1. 空输入处理
  2. 所有顾客都去一个窗口的情况
  3. 顾客数量不满足完整处理周期(如最后只剩1个A窗口顾客)
  4. 超大输入规模时的内存管理

Python优化版示例:

def optimized_bank_queue(customers): queue_a, queue_b = [], [] a_count = b_count = 0 # 分流并计数 for c in customers: if c % 2: queue_a.append(c) a_count += 1 else: queue_b.append(c) b_count += 1 result = [0] * len(customers) idx = 0 a_ptr = b_ptr = 0 # 使用处理周期概念 while a_ptr < a_count or b_ptr < b_count: # 处理两个A for _ in range(2): if a_ptr < a_count: result[idx] = queue_a[a_ptr] idx += 1 a_ptr += 1 else: break # 处理一个B if b_ptr < b_count: result[idx] = queue_b[b_ptr] idx += 1 b_ptr += 1 return result

这种实现避免了模运算,使用明确的处理周期概念,可能更易理解和维护。

7. 实际应用场景扩展

双队列调度模式在真实系统中有广泛应用:

  1. 操作系统调度

    • 高优先级和普通优先级任务队列
    • 实时进程和批处理进程调度
  2. 网络服务

    • VIP用户和普通用户请求分流
    • 不同QoS级别的数据包处理
  3. 游戏开发

    • 高优先级游戏事件(如用户输入)和低优先级事件(如AI计算)处理
  4. 工业生产

    • 快速生产线和慢速生产线的任务分配

理解这一模式后,可以灵活调整应用于各种需要差异化服务的场景。关键在于识别出问题中的三个要素:分流规则、处理比例和输出要求。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 21:33:24

双非逆袭北邮网安:我的考研实战路线图与避坑指南

1. 从双非到北邮网安的逆袭之路 作为一个双非院校的普通学生&#xff0c;能够一战上岸北邮网安&#xff0c;我自己都觉得有些不可思议。记得刚开始准备考研时&#xff0c;身边不少人都觉得我是在做白日梦。但事实证明&#xff0c;只要方法得当、规划合理&#xff0c;双非背景同…

作者头像 李华
网站建设 2026/6/11 21:32:46

智能服务降级与流量预测:AI 云原生架构的自适应防护

智能服务降级与流量预测&#xff1a;AI 云原生架构的自适应防护一、静态降级策略的"刻舟求剑"&#xff1a;固定阈值为何总是失效 微服务架构中&#xff0c;服务降级是保护系统稳定性的最后一道防线。当系统负载超过阈值时&#xff0c;降级非核心功能、限制流量、返回…

作者头像 李华
网站建设 2026/6/11 21:30:59

终极FF14钓鱼计时器:渔人的直感智能辅助工具完整指南

终极FF14钓鱼计时器&#xff1a;渔人的直感智能辅助工具完整指南 【免费下载链接】Fishers-Intuition 渔人的直感&#xff0c;最终幻想14钓鱼计时器 项目地址: https://gitcode.com/gh_mirrors/fi/Fishers-Intuition 渔人的直感是一款专为《最终幻想14》设计的智能钓鱼计…

作者头像 李华
网站建设 2026/6/11 21:17:56

ComfyUI-LTXVideo:终极视频生成工具完整指南

ComfyUI-LTXVideo&#xff1a;终极视频生成工具完整指南 【免费下载链接】ComfyUI-LTXVideo LTX-Video Support for ComfyUI 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-LTXVideo 在AI视频生成技术快速发展的今天&#xff0c;ComfyUI-LTXVideo作为LTX-2…

作者头像 李华
网站建设 2026/6/11 21:16:05

【UCIe】Runtime Link Test 中的 Parity 机制:从原理到精准链路诊断

1. UCIe Runtime Link Test中的Parity机制是什么&#xff1f; 当你把两块芯片通过UCIe接口连接起来时&#xff0c;最担心的就是数据传输过程中出现错误。这就好比两个人在嘈杂的房间里对话&#xff0c;你总得有个方法确认对方听清楚了你说的话。UCIe的Runtime Link Test中的Par…

作者头像 李华
网站建设 2026/6/11 21:15:52

Keil MDK下ARMCC V5标准库源码集:含C++容器、IO流与运行时头文件

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;专为Keil MDK中需切换回ARMCC 5.x编译器的嵌入式项目准备&#xff0c;提供完整可集成的标准库源码支持。包含algorithm、vector、string、iostream等常用C组件的.cc实现文件&#xff08;如istream.cc、ostream.…

作者头像 李华